# Table of Contents - [Documentation | OpenTofu](#documentation-opentofu) - [OpenTofu](#opentofu) - [OpenTofu CLI Documentation | OpenTofu](#opentofu-cli-documentation-opentofu) - [CLI Authentication | OpenTofu](#cli-authentication-opentofu) - [Using the Cloud Backend with OpenTofu CLI | OpenTofu](#using-the-cloud-backend-with-opentofu-cli-opentofu) - [Command Line Arguments | OpenTofu](#command-line-arguments-opentofu) - [Writing and Modifying OpenTofu Code | OpenTofu](#writing-and-modifying-opentofu-code-opentofu) - [Initializing and Migrating | OpenTofu](#initializing-and-migrating-opentofu) - [Cloud Backend Settings | OpenTofu](#cloud-backend-settings-opentofu) - [Command: env | OpenTofu](#command-env-opentofu) - [Command: destroy | OpenTofu](#command-destroy-opentofu) - [Command: fmt | OpenTofu](#command-fmt-opentofu) - [Basic CLI Features | OpenTofu](#basic-cli-features-opentofu) - [Command: force-unlock | OpenTofu](#command-force-unlock-opentofu) - [Command: apply | OpenTofu](#command-apply-opentofu) - [Command: get | OpenTofu](#command-get-opentofu) - [Command: console | OpenTofu](#command-console-opentofu) - [Command: login | OpenTofu](#command-login-opentofu) - [CLI Configuration | OpenTofu](#cli-configuration-opentofu) - [Command: logout | OpenTofu](#command-logout-opentofu) - [Command: graph | OpenTofu](#command-graph-opentofu) - [Command: providers | OpenTofu](#command-providers-opentofu) - [Command: providers mirror | OpenTofu](#command-providers-mirror-opentofu) - [Resource Importability | OpenTofu](#resource-importability-opentofu) - [Initializing Working Directories | OpenTofu](#initializing-working-directories-opentofu) - [Import | OpenTofu](#import-opentofu) - [Inspecting Infrastructure | OpenTofu](#inspecting-infrastructure-opentofu) - [Command: output | OpenTofu](#command-output-opentofu) - [Command: init | OpenTofu](#command-init-opentofu) - [Command: providers lock | OpenTofu](#command-providers-lock-opentofu) - [Command: providers schema | OpenTofu](#command-providers-schema-opentofu) - [Command: state | OpenTofu](#command-state-opentofu) - [Environment Variables | OpenTofu](#environment-variables-opentofu) - [Command: import | OpenTofu](#command-import-opentofu) - [Command: refresh | OpenTofu](#command-refresh-opentofu) - [Command: show | OpenTofu](#command-show-opentofu) - [Import Usage | OpenTofu](#import-usage-opentofu) - [Private Registries | OpenTofu](#private-registries-opentofu) - [Plugin Signing | OpenTofu](#plugin-signing-opentofu) - [OCI Registry Integrations | OpenTofu](#oci-registry-integrations-opentofu) - [Command: state list | OpenTofu](#command-state-list-opentofu) - [Provisioning Infrastructure with OpenTofu | OpenTofu](#provisioning-infrastructure-with-opentofu-opentofu) - [Command: plan | OpenTofu](#command-plan-opentofu) - [OpenTofu Internals | OpenTofu](#opentofu-internals-opentofu) - [Module Packages in OCI Registries | OpenTofu](#module-packages-in-oci-registries-opentofu) - [OCI Registry Credentials | OpenTofu](#oci-registry-credentials-opentofu) - [Managing Plugins | OpenTofu](#managing-plugins-opentofu) - [Credentials Helpers | OpenTofu](#credentials-helpers-opentofu) - [Debugging OpenTofu | OpenTofu](#debugging-opentofu-opentofu) - [Recovering from State Disasters | OpenTofu](#recovering-from-state-disasters-opentofu) - [Moving Resources | OpenTofu](#moving-resources-opentofu) - [CLI Configuration File | OpenTofu](#cli-configuration-file-opentofu) - [Inspecting State | OpenTofu](#inspecting-state-opentofu) - [Manipulating OpenTofu State | OpenTofu](#manipulating-opentofu-state-opentofu) - [Command: state push | OpenTofu](#command-state-push-opentofu) - [Command: state pull | OpenTofu](#command-state-pull-opentofu) - [Command: state replace-provider | OpenTofu](#command-state-replace-provider-opentofu) - [Command: taint | OpenTofu](#command-taint-opentofu) - [Provider Mirrors in OCI Registries | OpenTofu](#provider-mirrors-in-oci-registries-opentofu) - [Resource Graph | OpenTofu](#resource-graph-opentofu) - [Server-side Login Protocol | OpenTofu](#server-side-login-protocol-opentofu) - [Functions Metadata | OpenTofu](#functions-metadata-opentofu) - [Command: workspace | OpenTofu](#command-workspace-opentofu) - [Managing Workspaces | OpenTofu](#managing-workspaces-opentofu) - [Provider Metadata | OpenTofu](#provider-metadata-opentofu) - [Getting started | OpenTofu](#getting-started-opentofu) - [Forcing Re-creation of Resources | OpenTofu](#forcing-re-creation-of-resources-opentofu) - [Command: workspace show | OpenTofu](#command-workspace-show-opentofu) - [Resource Addressing | OpenTofu](#resource-addressing-opentofu) - [Working with OpenTofu | OpenTofu](#working-with-opentofu-opentofu) - [Command: version | OpenTofu](#command-version-opentofu) - [Command: state show | OpenTofu](#command-state-show-opentofu) - [Command: untaint | OpenTofu](#command-untaint-opentofu) - [Command: workspace delete | OpenTofu](#command-workspace-delete-opentofu) - [Command: workspace new | OpenTofu](#command-workspace-new-opentofu) - [Command: state rm | OpenTofu](#command-state-rm-opentofu) - [Command: state mv | OpenTofu](#command-state-mv-opentofu) - [Command: workspace list | OpenTofu](#command-workspace-list-opentofu) - [Remote Service Discovery | OpenTofu](#remote-service-discovery-opentofu) - [Command: workspace select | OpenTofu](#command-workspace-select-opentofu) - [OpenTelemetry Tracing | OpenTofu](#opentelemetry-tracing-opentofu) - [Migrating to OpenTofu from Terraform | OpenTofu](#migrating-to-opentofu-from-terraform-opentofu) - [Command: validate | OpenTofu](#command-validate-opentofu) - [Module Registry Protocol | OpenTofu](#module-registry-protocol-opentofu) - [Provider Registry Protocol | OpenTofu](#provider-registry-protocol-opentofu) - [What are TACOS? | OpenTofu](#what-are-tacos-opentofu) - [Provider Network Mirror Protocol | OpenTofu](#provider-network-mirror-protocol-opentofu) - [Installing OpenTofu on FreeBSD | OpenTofu](#installing-opentofu-on-freebsd-opentofu) - [Use Cases | OpenTofu](#use-cases-opentofu) - [Installing OpenTofu on Alpine Linux | OpenTofu](#installing-opentofu-on-alpine-linux-opentofu) - [Migration Guide | OpenTofu](#migration-guide-opentofu) - [Installing OpenTofu via Homebrew | OpenTofu](#installing-opentofu-via-homebrew-opentofu) - [Installing OpenTofu on Fedora | OpenTofu](#installing-opentofu-on-fedora-opentofu) - [Upgrading from OpenTofu 1.7.x/1.8.x/1.9.x | OpenTofu](#upgrading-from-opentofu-1-7-x-1-8-x-1-9-x-opentofu) - [Installing OpenTofu via Snapcraft (Linux) | OpenTofu](#installing-opentofu-via-snapcraft-linux-opentofu) - [Installing OpenTofu | OpenTofu](#installing-opentofu-opentofu) - [OpenTofu vs. Alternatives | OpenTofu](#opentofu-vs-alternatives-opentofu) - [OpenTofu vs. Boto, Fog, etc. | OpenTofu](#opentofu-vs-boto-fog-etc-opentofu) - [OpenTofu vs. CloudFormation, Heat, etc. | OpenTofu](#opentofu-vs-cloudformation-heat-etc-opentofu) - [OpenTofu vs. Chef, Puppet, etc. | OpenTofu](#opentofu-vs-chef-puppet-etc-opentofu) - [Installing OpenTofu from GitHub Releases | OpenTofu](#installing-opentofu-from-github-releases-opentofu) - [Building a Docker Image with OpenTofu | OpenTofu](#building-a-docker-image-with-opentofu-opentofu) - [Installing OpenTofu on .deb-based Linux (Debian, Ubuntu, etc.) | OpenTofu](#installing-opentofu-on-deb-based-linux-debian-ubuntu-etc-opentofu) - [Machine-Readable UI | OpenTofu](#machine-readable-ui-opentofu) - [OpenTofu vs. Custom Solutions | OpenTofu](#opentofu-vs-custom-solutions-opentofu) - [Installing OpenTofu on RHEL, openSUSE, AlmaLinux and other RPM-based distributions | OpenTofu](#installing-opentofu-on-rhel-opensuse-almalinux-and-other-rpm-based-distributions-opentofu) - [Installing OpenTofu from GitHub Releases | OpenTofu](#installing-opentofu-from-github-releases-opentofu) - [What's new in OpenTofu 1.10? | OpenTofu](#what-s-new-in-opentofu-1-10-opentofu) - [Command: test | OpenTofu](#command-test-opentofu) - [OpenTofu Language Documentation | OpenTofu](#opentofu-language-documentation-opentofu) - [Checks | OpenTofu](#checks-opentofu) - [Attributes as Blocks | OpenTofu](#attributes-as-blocks-opentofu) - [JSON Output Format | OpenTofu](#json-output-format-opentofu) - [Files and Directories | OpenTofu](#files-and-directories-opentofu) - [Data Sources | OpenTofu](#data-sources-opentofu) - [Override Files | OpenTofu](#override-files-opentofu) - [Expressions | OpenTofu](#expressions-opentofu) - [Conditional Expressions | OpenTofu](#conditional-expressions-opentofu) - [Splat Expressions | OpenTofu](#splat-expressions-opentofu) - [Arithmetic and Logical Operators | OpenTofu](#arithmetic-and-logical-operators-opentofu) - [Types and Values | OpenTofu](#types-and-values-opentofu) - [Dynamic Blocks | OpenTofu](#dynamic-blocks-opentofu) - [Dependency Lock File | OpenTofu](#dependency-lock-file-opentofu) - [For Expressions | OpenTofu](#for-expressions-opentofu) - [Strings and Templates | OpenTofu](#strings-and-templates-opentofu) - [Function Calls | OpenTofu](#function-calls-opentofu) - [Version Constraints | OpenTofu](#version-constraints-opentofu) - [References to Named Values | OpenTofu](#references-to-named-values-opentofu) - [Type Constraints | OpenTofu](#type-constraints-opentofu) - [Custom Conditions | OpenTofu](#custom-conditions-opentofu) - [Generating configuration | OpenTofu](#generating-configuration-opentofu) - [Built-in Provider | OpenTofu](#built-in-provider-opentofu) - [Publishing Modules | OpenTofu](#publishing-modules-opentofu) - [Creating Modules | OpenTofu](#creating-modules-opentofu) - [The depends_on Meta-Argument | OpenTofu](#the-depends-on-meta-argument-opentofu) - [Provisioners Without a Resource | OpenTofu](#provisioners-without-a-resource-opentofu) - [OpenTofu CLI Documentation | OpenTofu](#opentofu-cli-documentation-opentofu) - [The Resource provider Meta-Argument | OpenTofu](#the-resource-provider-meta-argument-opentofu) - [Resources | OpenTofu](#resources-opentofu) - [Modules | OpenTofu](#modules-opentofu) - [Import | OpenTofu](#import-opentofu) - [Standard Module Structure | OpenTofu](#standard-module-structure-opentofu) - [Resource Behavior | OpenTofu](#resource-behavior-opentofu) - [remote-exec Provisioner | OpenTofu](#remote-exec-provisioner-opentofu) - [local-exec Provisioner | OpenTofu](#local-exec-provisioner-opentofu) - [File Provisioner | OpenTofu](#file-provisioner-opentofu) - [Using the Cloud Backend with OpenTofu CLI | OpenTofu](#using-the-cloud-backend-with-opentofu-cli-opentofu) - [Command Line Arguments | OpenTofu](#command-line-arguments-opentofu) - [CLI Authentication | OpenTofu](#cli-authentication-opentofu) - [Backend Type: consul | OpenTofu](#backend-type-consul-opentofu) - [Backend Type: http | OpenTofu](#backend-type-http-opentofu) - [Upgrading to OpenTofu v1.6 | OpenTofu](#upgrading-to-opentofu-v1-6-opentofu) - [The lifecycle Meta-Argument | OpenTofu](#the-lifecycle-meta-argument-opentofu) - [Cloud Configuration | OpenTofu](#cloud-configuration-opentofu) - [Backend Type: local | OpenTofu](#backend-type-local-opentofu) - [The count Meta-Argument | OpenTofu](#the-count-meta-argument-opentofu) - [Providers | OpenTofu](#providers-opentofu) - [The Module providers Meta-Argument | OpenTofu](#the-module-providers-meta-argument-opentofu) - [OpenTofu Settings | OpenTofu](#opentofu-settings-opentofu) - [The terraform_data Managed Resource Type | OpenTofu](#the-terraform-data-managed-resource-type-opentofu) - [Provisioner Connection Settings | OpenTofu](#provisioner-connection-settings-opentofu) - [Variables and Outputs | OpenTofu](#variables-and-outputs-opentofu) - [Writing and Modifying OpenTofu Code | OpenTofu](#writing-and-modifying-opentofu-code-opentofu) - [Backend Type: kubernetes | OpenTofu](#backend-type-kubernetes-opentofu) - [Providers Within Modules | OpenTofu](#providers-within-modules-opentofu) - [Syntax | OpenTofu](#syntax-opentofu) - [Backend Type: COS | OpenTofu](#backend-type-cos-opentofu) - [Initializing and Migrating | OpenTofu](#initializing-and-migrating-opentofu) - [Backend Type: gcs | OpenTofu](#backend-type-gcs-opentofu) - [Backend Type: oss | OpenTofu](#backend-type-oss-opentofu) - [Module Composition | OpenTofu](#module-composition-opentofu) - [Backend Type: azurerm | OpenTofu](#backend-type-azurerm-opentofu) - [What are TACOS? | OpenTofu](#what-are-tacos-opentofu) - [CLI Configuration | OpenTofu](#cli-configuration-opentofu) - [Backend Configuration | OpenTofu](#backend-configuration-opentofu) - [Style Conventions | OpenTofu](#style-conventions-opentofu) - [The for_each Meta-Argument | OpenTofu](#the-for-each-meta-argument-opentofu) - [Import Existing Resources | OpenTofu](#import-existing-resources-opentofu) - [Provider Configuration | OpenTofu](#provider-configuration-opentofu) - [Configuration Syntax | OpenTofu](#configuration-syntax-opentofu) - [Local Values | OpenTofu](#local-values-opentofu) - [Cloud Backend Settings | OpenTofu](#cloud-backend-settings-opentofu) - [OpenTofu Internals | OpenTofu](#opentofu-internals-opentofu) - [Backend Type: pg | OpenTofu](#backend-type-pg-opentofu) - [Module Blocks | OpenTofu](#module-blocks-opentofu) - [Sensitive Data in State | OpenTofu](#sensitive-data-in-state-opentofu) - [State Storage and Locking | OpenTofu](#state-storage-and-locking-opentofu) - [Provider Requirements | OpenTofu](#provider-requirements-opentofu) - [Provisioners | OpenTofu](#provisioners-opentofu) - [Debugging OpenTofu | OpenTofu](#debugging-opentofu-opentofu) - [Getting started | OpenTofu](#getting-started-opentofu) - [Migrating to OpenTofu from Terraform | OpenTofu](#migrating-to-opentofu-from-terraform-opentofu) - [Working with OpenTofu | OpenTofu](#working-with-opentofu-opentofu) - [Use Cases | OpenTofu](#use-cases-opentofu) - [Resource Importability | OpenTofu](#resource-importability-opentofu) - [State Locking | OpenTofu](#state-locking-opentofu) - [Plugin Signing | OpenTofu](#plugin-signing-opentofu) - [Private Registries | OpenTofu](#private-registries-opentofu) - [Server-side Login Protocol | OpenTofu](#server-side-login-protocol-opentofu) - [Provider Metadata | OpenTofu](#provider-metadata-opentofu) - [What's new in OpenTofu 1.11? | OpenTofu](#what-s-new-in-opentofu-1-11-opentofu) - [Upgrading from OpenTofu 1.8.x/1.9.x/1.10.x | OpenTofu](#upgrading-from-opentofu-1-8-x-1-9-x-1-10-x-opentofu) - [Purpose of OpenTofu State | OpenTofu](#purpose-of-opentofu-state-opentofu) - [Backend Type: remote | OpenTofu](#backend-type-remote-opentofu) - [Initializing Working Directories | OpenTofu](#initializing-working-directories-opentofu) - [Functions Metadata | OpenTofu](#functions-metadata-opentofu) - [OpenTofu vs. Alternatives | OpenTofu](#opentofu-vs-alternatives-opentofu) - [OpenTofu vs. Boto, Fog, etc. | OpenTofu](#opentofu-vs-boto-fog-etc-opentofu) - [OpenTofu vs. Custom Solutions | OpenTofu](#opentofu-vs-custom-solutions-opentofu) - [OpenTofu vs. Chef, Puppet, etc. | OpenTofu](#opentofu-vs-chef-puppet-etc-opentofu) - [Migration Guide | OpenTofu](#migration-guide-opentofu) - [Remote State | OpenTofu](#remote-state-opentofu) - [Remote Service Discovery | OpenTofu](#remote-service-discovery-opentofu) - [Credentials Helpers | OpenTofu](#credentials-helpers-opentofu) - [Module Registry Protocol | OpenTofu](#module-registry-protocol-opentofu) - [OpenTofu vs. CloudFormation, Heat, etc. | OpenTofu](#opentofu-vs-cloudformation-heat-etc-opentofu) - [Refactoring | OpenTofu](#refactoring-opentofu) - [Resource Blocks | OpenTofu](#resource-blocks-opentofu) - [OCI Registry Integrations | OpenTofu](#oci-registry-integrations-opentofu) - [Provisioning Infrastructure with OpenTofu | OpenTofu](#provisioning-infrastructure-with-opentofu-opentofu) - [Resource Graph | OpenTofu](#resource-graph-opentofu) - [Workspaces | OpenTofu](#workspaces-opentofu) - [Module Sources | OpenTofu](#module-sources-opentofu) - [Import | OpenTofu](#import-opentofu) - [Import Usage | OpenTofu](#import-usage-opentofu) - [Provider Network Mirror Protocol | OpenTofu](#provider-network-mirror-protocol-opentofu) - [State | OpenTofu](#state-opentofu) - [Recovering from State Disasters | OpenTofu](#recovering-from-state-disasters-opentofu) - [Inspecting State | OpenTofu](#inspecting-state-opentofu) - [Moving Resources | OpenTofu](#moving-resources-opentofu) - [Module Packages in OCI Registries | OpenTofu](#module-packages-in-oci-registries-opentofu) - [Installing OpenTofu | OpenTofu](#installing-opentofu-opentofu) - [Manipulating OpenTofu State | OpenTofu](#manipulating-opentofu-state-opentofu) - [JSON Configuration Syntax | OpenTofu](#json-configuration-syntax-opentofu) - [OCI Registry Credentials | OpenTofu](#oci-registry-credentials-opentofu) - [Installing OpenTofu on Alpine Linux | OpenTofu](#installing-opentofu-on-alpine-linux-opentofu) - [Installing OpenTofu on FreeBSD | OpenTofu](#installing-opentofu-on-freebsd-opentofu) - [Installing OpenTofu on Fedora | OpenTofu](#installing-opentofu-on-fedora-opentofu) - [Installing OpenTofu via Homebrew | OpenTofu](#installing-opentofu-via-homebrew-opentofu) - [Installing OpenTofu via Snapcraft (Linux) | OpenTofu](#installing-opentofu-via-snapcraft-linux-opentofu) - [Output Values | OpenTofu](#output-values-opentofu) - [Managing Plugins | OpenTofu](#managing-plugins-opentofu) - [Forcing Re-creation of Resources | OpenTofu](#forcing-re-creation-of-resources-opentofu) - [Installing OpenTofu from GitHub Releases | OpenTofu](#installing-opentofu-from-github-releases-opentofu) - [Environment Variables | OpenTofu](#environment-variables-opentofu) - [Provider Registry Protocol | OpenTofu](#provider-registry-protocol-opentofu) - [Managing Workspaces | OpenTofu](#managing-workspaces-opentofu) - [Installing OpenTofu on .deb-based Linux (Debian, Ubuntu, etc.) | OpenTofu](#installing-opentofu-on-deb-based-linux-debian-ubuntu-etc-opentofu) - [Inspecting Infrastructure | OpenTofu](#inspecting-infrastructure-opentofu) - [The terraform_remote_state Data Source | OpenTofu](#the-terraform-remote-state-data-source-opentofu) - [Resource Addressing | OpenTofu](#resource-addressing-opentofu) - [Building a Docker Image with OpenTofu | OpenTofu](#building-a-docker-image-with-opentofu-opentofu) - [Installing OpenTofu on RHEL, openSUSE, AlmaLinux and other RPM-based distributions | OpenTofu](#installing-opentofu-on-rhel-opensuse-almalinux-and-other-rpm-based-distributions-opentofu) - [Documentation | OpenTofu](#documentation-opentofu) - [Provider Mirrors in OCI Registries | OpenTofu](#provider-mirrors-in-oci-registries-opentofu) - [Input Variables | OpenTofu](#input-variables-opentofu) - [Write-only attributes | OpenTofu](#write-only-attributes-opentofu) - [Backend Type: s3 | OpenTofu](#backend-type-s3-opentofu) - [Installing OpenTofu from GitHub Releases | OpenTofu](#installing-opentofu-from-github-releases-opentofu) - [OpenTofu Language Documentation | OpenTofu](#opentofu-language-documentation-opentofu) - [Machine-Readable UI | OpenTofu](#machine-readable-ui-opentofu) - [Command: env | OpenTofu](#command-env-opentofu) - [Command: logout | OpenTofu](#command-logout-opentofu) - [Files and Directories | OpenTofu](#files-and-directories-opentofu) - [Attributes as Blocks | OpenTofu](#attributes-as-blocks-opentofu) - [Override Files | OpenTofu](#override-files-opentofu) - [Command: login | OpenTofu](#command-login-opentofu) - [Command: fmt | OpenTofu](#command-fmt-opentofu) - [Command: force-unlock | OpenTofu](#command-force-unlock-opentofu) - [Command: destroy | OpenTofu](#command-destroy-opentofu) - [Checks | OpenTofu](#checks-opentofu) - [Command: get | OpenTofu](#command-get-opentofu) - [Basic CLI Features | OpenTofu](#basic-cli-features-opentofu) - [Data Sources | OpenTofu](#data-sources-opentofu) - [Command: graph | OpenTofu](#command-graph-opentofu) - [Command: workspace | OpenTofu](#command-workspace-opentofu) - [Command: state | OpenTofu](#command-state-opentofu) - [Ephemeral resources | OpenTofu](#ephemeral-resources-opentofu) - [Command: apply | OpenTofu](#command-apply-opentofu) - [CLI Configuration File | OpenTofu](#cli-configuration-file-opentofu) - [Command: refresh | OpenTofu](#command-refresh-opentofu) - [Command: show | OpenTofu](#command-show-opentofu) - [Command: version | OpenTofu](#command-version-opentofu) - [Command: workspace show | OpenTofu](#command-workspace-show-opentofu) - [Command: providers | OpenTofu](#command-providers-opentofu) - [Expressions | OpenTofu](#expressions-opentofu) - [Command: untaint | OpenTofu](#command-untaint-opentofu) - [Command: taint | OpenTofu](#command-taint-opentofu) - [Command: providers mirror | OpenTofu](#command-providers-mirror-opentofu) - [Command: state push | OpenTofu](#command-state-push-opentofu) - [Command: state pull | OpenTofu](#command-state-pull-opentofu) - [Command: workspace new | OpenTofu](#command-workspace-new-opentofu) - [Command: workspace list | OpenTofu](#command-workspace-list-opentofu) - [Command: workspace delete | OpenTofu](#command-workspace-delete-opentofu) - [OpenTofu CLI Documentation | OpenTofu](#opentofu-cli-documentation-opentofu) - [Command: workspace select | OpenTofu](#command-workspace-select-opentofu) - [Ephemerality | OpenTofu](#ephemerality-opentofu) - [Dependency Lock File | OpenTofu](#dependency-lock-file-opentofu) - [CLI Authentication | OpenTofu](#cli-authentication-opentofu) - [Command: init | OpenTofu](#command-init-opentofu) - [Command: state list | OpenTofu](#command-state-list-opentofu) - [Command: console | OpenTofu](#command-console-opentofu) - [Command: output | OpenTofu](#command-output-opentofu) - [Command: providers schema | OpenTofu](#command-providers-schema-opentofu) - [OpenTofu v1.x Compatibility Promises | OpenTofu](#opentofu-v1-x-compatibility-promises-opentofu) - [Version Constraints | OpenTofu](#version-constraints-opentofu) - [Arithmetic and Logical Operators | OpenTofu](#arithmetic-and-logical-operators-opentofu) - [Conditional Expressions | OpenTofu](#conditional-expressions-opentofu) - [Command Line Arguments | OpenTofu](#command-line-arguments-opentofu) - [Using the Cloud Backend with OpenTofu CLI | OpenTofu](#using-the-cloud-backend-with-opentofu-cli-opentofu) - [Splat Expressions | OpenTofu](#splat-expressions-opentofu) - [Command: import | OpenTofu](#command-import-opentofu) - [Command: providers lock | OpenTofu](#command-providers-lock-opentofu) - [Command: validate | OpenTofu](#command-validate-opentofu) - [Types and Values | OpenTofu](#types-and-values-opentofu) - [Command: state show | OpenTofu](#command-state-show-opentofu) - [Command: state replace-provider | OpenTofu](#command-state-replace-provider-opentofu) - [Writing and Modifying OpenTofu Code | OpenTofu](#writing-and-modifying-opentofu-code-opentofu) - [Migrating to OpenTofu 1.7.x from Terraform | OpenTofu](#migrating-to-opentofu-1-7-x-from-terraform-opentofu) - [Use Cases | OpenTofu](#use-cases-opentofu) - [Getting started | OpenTofu](#getting-started-opentofu) - [Command: state rm | OpenTofu](#command-state-rm-opentofu) - [Function Calls | OpenTofu](#function-calls-opentofu) - [Dynamic Blocks | OpenTofu](#dynamic-blocks-opentofu) - [For Expressions | OpenTofu](#for-expressions-opentofu) - [lifecycle Blocks | OpenTofu](#lifecycle-blocks-opentofu) - [Publishing Modules | OpenTofu](#publishing-modules-opentofu) - [Generating configuration | OpenTofu](#generating-configuration-opentofu) - [OpenTofu vs. Chef, Puppet, etc. | OpenTofu](#opentofu-vs-chef-puppet-etc-opentofu) - [Command: state mv | OpenTofu](#command-state-mv-opentofu) - [Strings and Templates | OpenTofu](#strings-and-templates-opentofu) - [Built-in Provider | OpenTofu](#built-in-provider-opentofu) --- # Documentation | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) ### OpenTofu Documentation Version: 1.11.x[​](https://opentofu.org/docs/v1.11/#opentofu-documentation- "Direct link to opentofu-documentation-") Welcome to OpenTofu 1.11! This version brings a lot of new features and improvements to OpenTofu. If you are coming from a previous OpenTofu or Terraform version you can [read the details about the new features here Β»](https://opentofu.org/docs/v1.11/intro/whats-new/) [Getting started](https://opentofu.org/docs/v1.11/intro/) ---------------------------------------------------------- Get started with OpenTofu or migrate from a previous version. This section has all the info you need. [Language](https://opentofu.org/docs/v1.11/language/) ------------------------------------------------------ Use the OpenTofu configuration language to describe the infrastructure that OpenTofu manages. [CLI Documentation](https://opentofu.org/docs/v1.11/cli/) ---------------------------------------------------------- Learn OpenTofu's CLI-based workflows. You can use the CLI alone or with cloud backends. [Internals](https://opentofu.org/docs/v1.11/internals/) -------------------------------------------------------- Learn how OpenTofu generates the resource dependency graph and executes other internal processes. --- # OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) ### OpenTofu Documentation Version: 1.10.x[​](https://opentofu.org/docs/v1.10/#opentofu-documentation- "Direct link to opentofu-documentation-") Welcome to OpenTofu 1.10! This version brings a lot of new features and improvements to OpenTofu. If you are coming from a previous OpenTofu or Terraform version you can [read the details about the new features here Β»](https://opentofu.org/docs/v1.10/intro/whats-new/) [Getting started](https://opentofu.org/docs/v1.10/intro/) ---------------------------------------------------------- Get started with OpenTofu or migrate from a previous version. This section has all the info you need. [Language](https://opentofu.org/docs/v1.10/language/) ------------------------------------------------------ Use the OpenTofu configuration language to describe the infrastructure that OpenTofu manages. [CLI Documentation](https://opentofu.org/docs/v1.10/cli/) ---------------------------------------------------------- Learn OpenTofu's CLI-based workflows. You can use the CLI alone or with cloud backends. [Internals](https://opentofu.org/docs/v1.10/internals/) -------------------------------------------------------- Learn how OpenTofu generates the resource dependency graph and executes other internal processes. --- # OpenTofu CLI Documentation | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu CLI Documentation ========================== This is the documentation for OpenTofu CLI. It is relevant to anyone working with OpenTofu's CLI-based workflows; this includes people who use OpenTofu CLI by itself, as well as those who use OpenTofu CLI in conjunction with [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software). Notably, this documentation does not cover the syntax and usage of the OpenTofu language. For that, see the [OpenTofu Language Documentation](https://opentofu.org/docs/v1.10/language/) . --- # CLI Authentication | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/auth/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) CLI Authentication ================== [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software) are platforms that perform as part of their offering OpenTofu runs to provision infrastructure, offering a collaboration-focused environment that makes it easier for teams to use OpenTofu together. OpenTofu CLI integrates with [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) in several ways β€”Β it can be a front-end for CLI-driven runs, and can also use some [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) as a state backend, a private module registry, or a private provider registry. All of these integrations require you to authenticate OpenTofu CLI with your [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) account. The best way to handle CLI authentication is with the `login` and `logout` commands, which help automate the process of getting an API token for your [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) user account. For details, see: * [The `tofu login` command](https://opentofu.org/docs/v1.10/cli/commands/login/) * [The `tofu logout` command](https://opentofu.org/docs/v1.10/cli/commands/logout/) --- # Using the Cloud Backend with OpenTofu CLI | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/cloud/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Using the Cloud Backend with OpenTofu CLI ========================================= The OpenTofu CLI lets you use cloud backends on the command line. When you use the cloud backend CLI workflow, operations like `tofu plan` or `tofu apply` are remotely executed in the cloud backend's run environment by default, with log output streaming to the local terminal. This lets you use cloud backend's features within the familiar OpenTofu CLI workflow. Cloud backend services may choose to implement only a subset of the available features. Workspaces can also be configured for local execution, in which case the cloud backend only stores state. In this mode, the cloud backend behaves just like a standard state backend. Documentation Summary[​](https://opentofu.org/docs/v1.10/cli/cloud/#documentation-summary "Direct link to Documentation Summary") ---------------------------------------------------------------------------------------------------------------------------------- * [Cloud Backend Settings](https://opentofu.org/docs/v1.10/cli/cloud/settings/) documents the `cloud` block that you must add to your configuration to enable cloud backend support. * [Initializing and Migrating](https://opentofu.org/docs/v1.10/cli/cloud/migrating/) describes how to start using the cloud backend with a working directory that already has state data. * [Command Line Arguments](https://opentofu.org/docs/v1.10/cli/cloud/command-line-arguments/) lists the OpenTofu command flags that are specific to using OpenTofu with the cloud backend. * [Documentation Summary](https://opentofu.org/docs/v1.10/cli/cloud/#documentation-summary) --- # Command Line Arguments | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/cloud/command-line-arguments/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Command Line Arguments ====================== When your configuration includes a `cloud` block, commands that make local modifications to OpenTofu state and then push them back up to the remote workspace accept the following option to modify that behavior: * `-ignore-remote-version` - Override checking that the local and remote OpenTofu versions agree, making an operation proceed even when there is a mismatch. State-modification operations usually require using a local version of the OpenTofu CLI that is compatible with the OpenTofu version selected in the remote workspace settings. This prevents the local operation from creating a new state snapshot that the workspace's remote execution environment cannot decode. We recommend against using this option unless absolutely necessary. Overriding this check can result in a cloud backend workspace that is no longer able to complete remote operations with the currently selected version of OpenTofu. --- # Writing and Modifying OpenTofu Code | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/code/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Writing and Modifying OpenTofu Code =================================== The [OpenTofu language](https://opentofu.org/docs/v1.10/language/) is OpenTofu's primary user interface, and all of OpenTofu's workflows rely on configurations written in the OpenTofu language. OpenTofu CLI includes several commands to make OpenTofu code more convenient to work with. Integrating these commands into your editing workflow can potentially save you time and effort. * [The `tofu console` command](https://opentofu.org/docs/v1.10/cli/commands/console/) starts an interactive shell for evaluating OpenTofu [expressions](https://opentofu.org/docs/v1.10/language/expressions/) , which can be a faster way to verify that a particular resource argument results in the value you expect. * [The `tofu fmt` command](https://opentofu.org/docs/v1.10/cli/commands/fmt/) rewrites OpenTofu configuration files to a canonical format and style, so you don't have to waste time making minor adjustments for readability and consistency. It works well as a pre-commit hook in your version control system. * [The `tofu validate` command](https://opentofu.org/docs/v1.10/cli/commands/validate/) validates the syntax and arguments of the OpenTofu configuration files in a directory, including argument and attribute names and types for resources and modules. The `plan` and `apply` commands automatically validate a configuration before performing any other work, so `validate` isn't a crucial part of the core workflow, but it can be very useful as a pre-commit hook or as part of a continuous integration pipeline. --- # Initializing and Migrating | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/cloud/migrating/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Initializing and Migrating ========================== After [configuring cloud backend settings](https://opentofu.org/docs/v1.10/cli/cloud/settings/) for a working directory, you must run `tofu init` to finish setting up. If the working directory has no existing OpenTofu state, you can start using OpenTofu with a cloud backend right away. When you run `tofu init` in the following scenarios, OpenTofu will ask you to choose whether or not to migrate state from any existing workspaces. 1. [**Migrating from local state or state backends:**](https://opentofu.org/docs/v1.10/cli/cloud/migrating/#migrating-from-local-state-or-state-backends) If the working directory already has state data in one or more workspaces, OpenTofu will ask if you would like to migrate that state to new cloud backend workspaces. 2. [**Migrating from the `remote` backend:**](https://opentofu.org/docs/v1.10/cli/cloud/migrating/#migrating-from-the-remote-backend) If the working directory was already connected to a cloud backend with the `remote` backend, OpenTofu can continue using the same cloud backend workspaces. You will need to switch the `remote` backend block to the `cloud` block. Migrating from Local State or State Backends[​](https://opentofu.org/docs/v1.10/cli/cloud/migrating/#migrating-from-local-state-or-state-backends "Direct link to Migrating from Local State or State Backends") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If the working directory already has state data available (using either local state or a [state backend](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) ), OpenTofu asks your approval to migrate that state to the cloud backend. You will need permission to manage workspaces in the destination cloud backend organization. This process is interactive and self-documenting, and resembles moving between state backends. OpenTofu may also prompt you to rename your workspaces during the migration, to either give a name to the unnamed `default` workspace (the cloud backend requires all workspaces to have a name) or give your workspace names more contextual information. Unlike OpenTofu CLI-only workspaces, which represent multiple environments associated with the same configuration (e.g. production, staging, development), cloud backend workspaces can represent totally independent configurations, and must have unique names within the cloud backend organization. Because of this, OpenTofu will prompt you to rename the working directory's workspaces according to a pattern relative to their existing names. This can indicate the fact that these specific workspaces share configuration. A typical strategy is `--` (e.g., `networking-prod-us-east`, `networking-staging-us-east`). Migrating from the `remote` Backend[​](https://opentofu.org/docs/v1.10/cli/cloud/migrating/#migrating-from-the-remote-backend "Direct link to migrating-from-the-remote-backend") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If the working directory was already connected to a cloud backend with the `remote` backend, OpenTofu can continue using the same cloud backend workspaces. The local names shown for those workspaces will change to match their remote names. The [`remote` backend](https://opentofu.org/docs/v1.10/language/settings/backends/remote/) was the primary implementation for cloud backends for Terraform versions 0.11.13 through 1.0.x. We recommend using the native `cloud` integration for OpenTofu and Terraform versions 1.1 or later, as it provides an improved user experience and various enhancements. ### Block Replacement[​](https://opentofu.org/docs/v1.10/cli/cloud/migrating/#block-replacement "Direct link to Block Replacement") When switching from the `remote` backend to a `cloud` block, OpenTofu will continue using the same set of cloud backend workspaces. Replace your `backend "remote"` block with an equivalent `cloud` block. #### Single Workspace[​](https://opentofu.org/docs/v1.10/cli/cloud/migrating/#single-workspace "Direct link to Single Workspace") If you were using a single workspace with the `name` argument, change the block label to `cloud`. Code Block terraform {- backend "remote" {+ cloud { organization = "my-org" workspaces { name = "my-app-prod" } } } #### Multiple Workspaces[​](https://opentofu.org/docs/v1.10/cli/cloud/migrating/#multiple-workspaces "Direct link to Multiple Workspaces") If you were using multiple workspaces with the `prefix` argument, replace it with a `cloud` block that uses the `tags` argument. You may specify any number of tags to distinguish the workspaces for your working directory, but a good starting point may be to use whatever the prefix was before. The tags you configure do not need to be present on the existing workspaces. When you initialize, OpenTofu will add the specified tags to the workspaces if necessary. Code Block terraform {- backend "remote" {+ cloud { organization = "my-org" workspaces {- prefix = "my-app-"+ tags = ["app:mine"] } } } Warning Because the `cloud` block does not support the `prefix` argument, once you migrate, you must refer to workspaces by their full name when using the OpenTofu CLI. For example, rather than `tofu workspace select prod`, you must run the command `tofu workspace select my-app-prod`. * [Migrating from Local State or State Backends](https://opentofu.org/docs/v1.10/cli/cloud/migrating/#migrating-from-local-state-or-state-backends) * [Migrating from the `remote` Backend](https://opentofu.org/docs/v1.10/cli/cloud/migrating/#migrating-from-the-remote-backend) * [Block Replacement](https://opentofu.org/docs/v1.10/cli/cloud/migrating/#block-replacement) --- # Cloud Backend Settings | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/cloud/settings/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Cloud Backend Settings ====================== OpenTofu CLI can integrate with a cloud backend, acting as a client for it. You must configure the following settings to use the cloud backend for a particular working directory: * Provide credentials to access the cloud backend, preferably by using the [`tofu login`](https://opentofu.org/docs/v1.10/cli/commands/login/) command. * Add a `cloud` block to the directory's OpenTofu configuration, to specify which organization and workspace(s) to use. * Optionally, use a `.terraformignore` file to specify files that shouldn't be uploaded with the OpenTofu configuration when running plans and applies. After adding or changing a `cloud` block, you must run `tofu init`. The `cloud` Block[​](https://opentofu.org/docs/v1.10/cli/cloud/settings/#the-cloud-block "Direct link to the-cloud-block") --------------------------------------------------------------------------------------------------------------------------- The `cloud` block is a nested block within the top-level `terraform` settings block. It specifies which cloud backend workspaces to use for the current working directory. Code Block terraform { cloud { organization = "my-org" hostname = "app.example.org" workspaces { project = "networking-development" tags = ["networking", "source:cli"] } }} The `cloud` block also has some special restrictions: * A configuration can only provide one `cloud` block. * A `cloud` block cannot be used with [state backends](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) . A configuration can use one or the other, but not both. * A `cloud` block cannot refer to named values (like input variables, locals, or data source attributes). The `cloud` block only affects OpenTofu CLI's behavior. When the cloud backend uses a configuration that contains a cloud block - for example, when a workspace is configured to use a VCS provider directly - it ignores the block and behaves according to its own workspace settings. ### Arguments[​](https://opentofu.org/docs/v1.10/cli/cloud/settings/#arguments "Direct link to Arguments") The `cloud` block supports the following configuration arguments: * `hostname` - (Required) The hostname of the cloud backend. * `organization` - (Required) The name of the organization containing the workspace(s) the current configuration should use. * `workspaces` - (Required) A nested block that specifies which remote cloud backend workspaces to use for the current configuration. The `workspaces` block must contain **exactly one** of the following arguments, each denoting a strategy for how workspaces should be mapped: * `tags` - (Optional) A set of cloud backend workspace tags. You will be able to use this working directory with any workspaces that have all of the specified tags, and can use [the `tofu workspace` commands](https://opentofu.org/docs/v1.10/cli/workspaces/) to switch between them or create new workspaces. New workspaces will automatically have the specified tags. This option conflicts with `name`. * `name` - (Optional) The name of a single cloud backend workspace. You will only be able to use the workspace specified in the configuration with this working directory, and cannot manage workspaces from the CLI (e.g. `tofu workspace select` or `tofu workspace new`). This option conflicts with `tags`. * `project` - (Optional) The name of a cloud backend project. Workspaces that need created will will be created within this project. `tofu workspace list` will be filtered by workspaces in the supplied project. * `token` - (Optional) The token used to authenticate with the cloud backend. We recommend omitting the token from the configuration, and instead using [`tofu login`](https://opentofu.org/docs/v1.10/cli/commands/login/) or manually configuring `credentials` in the [CLI config file](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials) . ### Environment Variables[​](https://opentofu.org/docs/v1.10/cli/cloud/settings/#environment-variables "Direct link to Environment Variables") You can use environment variables to configure one or more `cloud` block attributes. This is helpful when you want to configure OpenTofu as part of a Continuous Integration (CI) pipeline. OpenTofu only reads these variables if the corresponding attribute is omitted from your configuration file. If you choose to configure the `cloud` block entirely through environment variables, you must still add an empty `cloud` block in your configuration file. Warning Remote execution with non-interactive workflows requires auto-approved deployments. Minimize risk of unpredictable infrastructure changes and configuration drift by making sure that no one can change your infrastructure outside of your automated build pipeline. Use the following environment variables to configure the `cloud` block: * `TF_CLOUD_ORGANIZATION` - The name of the organization. OpenTofu reads this variable when `organization` omitted from the `cloud` block. If both are specified, the configuration takes precedence. * `TF_CLOUD_HOSTNAME` - The hostname of the cloud backend. OpenTofu reads this when `hostname` is omitted from the `cloud` block. If both are specified, the configuration takes precedence. * `TF_CLOUD_PROJECT` - The name of a cloud backend project. OpenTofu reads this when `workspaces.project` is omitted from the `cloud` block. If both are specified, the cloud block configuration takes precedence. * `TF_WORKSPACE` - The name of a single cloud backend workspace. OpenTofu reads this when `workspaces` is omitted from the `cloud` block. The cloud backend will not create a new workspace from this variable; the workspace must exist in the specified organization. You can set `TF_WORKSPACE` if the `cloud` block uses tags. However, the selected `TF_WORKSPACE` must have a set of tags that match the tags in the `cloud` block. This variable also selects the workspace in your local environment. Refer to [TF\_WORKSPACE](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_workspace) for details. Excluding Files from Upload with .terraformignore[​](https://opentofu.org/docs/v1.10/cli/cloud/settings/#excluding-files-from-upload-with-terraformignore "Direct link to Excluding Files from Upload with .terraformignore") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ When executing a remote `plan` or `apply` in a CLI-driven run, a copy of your configuration directory is uploaded to the cloud backend. You can define paths to exclude from upload by adding a `.terraformignore` file at the root of your configuration directory. If this file is not present, the upload will exclude the following by default: * `.git/` directories * `.terraform/` directories (exclusive of `.terraform/modules`) The rules in `.terraformignore` file resemble the rules allowed in a [.gitignore file](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#_ignoring) : * Comments (starting with `#`) or blank lines are ignored. * End a pattern with a forward slash `/` to specify a directory. * Negate a pattern by starting it with an exclamation point `!`. Note Unlike `.gitignore`, only the `.terraformignore` at the root of the configuration directory is considered. * [The `cloud` Block](https://opentofu.org/docs/v1.10/cli/cloud/settings/#the-cloud-block) * [Arguments](https://opentofu.org/docs/v1.10/cli/cloud/settings/#arguments) * [Environment Variables](https://opentofu.org/docs/v1.10/cli/cloud/settings/#environment-variables) * [Excluding Files from Upload with .terraformignore](https://opentofu.org/docs/v1.10/cli/cloud/settings/#excluding-files-from-upload-with-terraformignore) --- # Command: env | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/env/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Command: env ============ The `tofu env` command is deprecated. [The `tofu workspace` command](https://opentofu.org/docs/v1.10/cli/commands/workspace/) should be used instead. --- # Command: destroy | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/destroy/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: destroy ================ The `tofu destroy` command is a convenient way to destroy all remote objects managed by a particular OpenTofu configuration. While you will typically not want to destroy long-lived objects in a production environment, OpenTofu is sometimes used to manage ephemeral infrastructure for development purposes, in which case you can use `tofu destroy` to conveniently clean up all of those temporary objects once you are finished with your work. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/destroy/#usage "Direct link to Usage") --------------------------------------------------------------------------------------------- Usage: `tofu destroy [options]` This command is just a convenience alias for the following command: Code Block tofu apply -destroy For that reason, this command accepts most of the options that [`tofu apply`](https://opentofu.org/docs/v1.10/cli/commands/apply/) accepts, although it does not accept a plan file argument and forces the selection of the "destroy" planning mode. You can also create a speculative destroy plan, to see what the effect of destroying would be, by running the following command: Code Block tofu plan -destroy This will run [`tofu plan`](https://opentofu.org/docs/v1.10/cli/commands/plan/) in _destroy_ mode, showing you the proposed destroy changes without executing them. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/destroy/#usage) --- # Command: fmt | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/fmt/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: fmt ============ The `tofu fmt` command is used to rewrite OpenTofu configuration files to a canonical format and style. This command applies a subset of the [OpenTofu language style conventions](https://opentofu.org/docs/v1.10/language/syntax/style/) , along with other minor adjustments for readability. Other OpenTofu commands that generate OpenTofu configuration will produce configuration files that conform to the style imposed by `tofu fmt`, so using this style in your own files will ensure consistency. The canonical format may change in minor ways between OpenTofu versions, so after upgrading OpenTofu we recommend to proactively run `tofu fmt` on your modules along with any other changes you are making to adopt the new version. We don't consider new formatting rules in `tofu fmt` to be a breaking change in new versions of OpenTofu, but we do aim to minimize changes for configurations that are already following the style examples shown in the OpenTofu documentation. When adding new formatting rules, they will usually aim to apply more of the rules already shown in the configuration examples in the documentation, and so we recommend following the documented style even for decisions that `tofu fmt` doesn't yet apply automatically. Formatting decisions are always subjective and so you might disagree with the decisions that `tofu fmt` makes. This command is intentionally opinionated and has no customization options because its primary goal is to encourage consistency of style between different OpenTofu codebases, even though the chosen style can never be everyone's favorite. We recommend that you follow the style conventions applied by `tofu fmt` when writing OpenTofu modules, but if you find the results particularly objectionable then you may choose not to use this command, and possibly choose to use a third-party formatting tool instead. If you choose to use a third-party tool then you should also run it on files that are generated automatically by OpenTofu, to get consistency between your hand-written files and the generated files. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/fmt/#usage "Direct link to Usage") ----------------------------------------------------------------------------------------- Usage: `tofu fmt [options] [target...]` By default, `fmt` scans the current directory for configuration files. If you provide a directory for the `target` argument, then `fmt` will scan that directory instead. If you provide a file, then `fmt` will process just that file. If you provide a single dash (`-`), then `fmt` will read from standard input (STDIN). The command-line flags are all optional. The following flags are available: * `-list=false` - Don't list the files containing formatting inconsistencies. * `-write=false` - Don't overwrite the input files. (This is implied by `-check` or when the input is STDIN.) * `-diff` - Display diffs of formatting changes. * When using this flag, ensure that `diff` tool is installed. This is used internally for providing a better user experience. * `-check` - Check if the input is formatted. Exit status will be 0 if all input is properly formatted. If not, exit status will be non-zero and the command will output a list of filenames whose files are not properly formatted. * `-recursive` - Also process files in subdirectories. By default, only the given directory (or current directory) is processed. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/fmt/#usage) --- # Basic CLI Features | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Basic CLI Features ================== The command line interface to OpenTofu is the `tofu` command, which accepts a variety of subcommands such as `tofu init` or `tofu plan`. To view a list of the commands available in your current OpenTofu version, run `tofu` with no additional arguments: Code Block Usage: tofu [global options] [args]The available commands for execution are listed below.The primary workflow commands are given first, followed byless common or more advanced commands.Main commands: init Prepare your working directory for other commands validate Check whether the configuration is valid plan Show changes required by the current configuration apply Create or update infrastructure destroy Destroy previously-created infrastructureAll other commands: console Try OpenTofu expressions at an interactive command prompt fmt Reformat your configuration in the standard style force-unlock Release a stuck lock on the current workspace get Install or upgrade remote OpenTofu modules graph Generate a Graphviz graph of the steps in an operation import Associate existing infrastructure with a OpenTofu resource login Obtain and save credentials for a remote host logout Remove locally-stored credentials for a remote host metadata Metadata related commands output Show output values from your root module providers Show the providers required for this configuration refresh Update the state to match remote systems show Show the current state or a saved plan state Advanced state management taint Mark a resource instance as not fully functional untaint Remove the 'tainted' state from a resource instance version Show the current OpenTofu version workspace Workspace managementGlobal options (use these before the subcommand, if any): -chdir=DIR Switch to a different working directory before executing the given subcommand. -help Show this help output, or the help for a specified subcommand. -version An alias for the "version" subcommand. (The output from your current OpenTofu version may be different than the above example.) To get specific help for any specific command, use the `-help` option with the relevant subcommand. For example, to see help about the "validate" subcommand you can run `tofu validate -help`. The inline help built in to OpenTofu CLI describes the most important characteristics of each command. For more detailed information, refer to each command's page for details. Switching working directory with `-chdir`[​](https://opentofu.org/docs/v1.10/cli/commands/#switching-working-directory-with--chdir "Direct link to switching-working-directory-with--chdir") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The usual way to run OpenTofu is to first switch to the directory containing the `.tf` or `.tofu` files for your root module (for example, using the `cd` command), so that OpenTofu will find those files automatically without any extra arguments. In some cases though β€” particularly when wrapping OpenTofu in automation scripts β€” it can be convenient to run OpenTofu from a different directory than the root module directory. To allow that, OpenTofu supports a global option `-chdir=...` which you can include before the name of the subcommand you intend to run: Code Block tofu -chdir=environments/production apply The `chdir` option instructs OpenTofu to change its working directory to the given directory before running the given subcommand. This means that any files that OpenTofu would normally read or write in the current working directory will be read or written in the given directory instead. There are two exceptions where OpenTofu will use the original working directory even when you specify `-chdir=...`: * Settings in the [CLI Configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/) are not for a specific subcommand and OpenTofu processes them before acting on the `-chdir` option. * In case you need to use files from the original working directory as part of your configuration, a reference to `path.cwd` in the configuration will produce the original working directory instead of the overridden working directory. Use `path.root` to get the root module directory. Shell Tab-completion[​](https://opentofu.org/docs/v1.10/cli/commands/#shell-tab-completion "Direct link to Shell Tab-completion") ---------------------------------------------------------------------------------------------------------------------------------- If you use either `bash` or `zsh` as your command shell, OpenTofu can provide tab-completion support for all command names and some command arguments. To add the necessary commands to your shell profile, run the following command: Code Block tofu -install-autocomplete After installation, it is necessary to restart your shell or to re-read its profile script before completion will be activated. To uninstall the completion hook, assuming that it has not been modified manually in the shell profile, run the following command: Code Block tofu -uninstall-autocomplete * [Switching working directory with `-chdir`](https://opentofu.org/docs/v1.10/cli/commands/#switching-working-directory-with--chdir) * [Shell Tab-completion](https://opentofu.org/docs/v1.10/cli/commands/#shell-tab-completion) --- # Command: force-unlock | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/force-unlock/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: force-unlock ===================== Manually unlock the state for the defined configuration. This will not modify your infrastructure. This command removes the lock on the state for the current configuration. The behavior of this lock is dependent on the backend being used. Local state files cannot be unlocked by another process. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/force-unlock/#usage "Direct link to Usage") -------------------------------------------------------------------------------------------------- Usage: `tofu force-unlock [options] LOCK_ID` Manually unlock the state for the defined configuration. This will not modify your infrastructure. This command removes the lock on the state for the current configuration. The behavior of this lock is dependent on the backend being used. Local state files cannot be unlocked by another process. Note Use of variables in [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu force-unlock`. Options: * `-force` - Don't ask for input for unlock confirmation. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/force-unlock/#usage) --- # Command: apply | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/apply/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: apply ============== The `tofu apply` command executes the actions proposed in a OpenTofu plan. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/apply/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------- Usage: `tofu apply [options] [plan file]` ### Automatic Plan Mode[​](https://opentofu.org/docs/v1.10/cli/commands/apply/#automatic-plan-mode "Direct link to Automatic Plan Mode") When you run `tofu apply` without passing a saved plan file, OpenTofu automatically creates a new execution plan as if you had run [`tofu plan`](https://opentofu.org/docs/v1.10/cli/commands/plan/) , prompts you to approve that plan, and takes the indicated actions. You can use all of the [planning modes](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-modes) and [planning options](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-options) to customize how OpenTofu will create the plan. You can pass the `-auto-approve` option to instruct OpenTofu to apply the plan without asking for confirmation. Warning If you use `-auto-approve`, we recommend making sure that no one can change your infrastructure outside of your OpenTofu workflow. This minimizes the risk of unpredictable changes and configuration drift. ### Saved Plan Mode[​](https://opentofu.org/docs/v1.10/cli/commands/apply/#saved-plan-mode "Direct link to Saved Plan Mode") When you pass a [saved plan file](https://opentofu.org/docs/v1.10/cli/commands/plan/#out-filename) to `tofu apply`, OpenTofu takes the actions in the saved plan without prompting you for confirmation. You may want to use this two-step workflow when running OpenTofu in automation. Use [`tofu show`](https://opentofu.org/docs/v1.10/cli/commands/show/) to inspect a saved plan file before applying it. When using a saved plan, you cannot specify any additional planning modes or options. These options only affect OpenTofu's decisions about which actions to take, and the plan file contains the final results of those decisions. ### Plan Options[​](https://opentofu.org/docs/v1.10/cli/commands/apply/#plan-options "Direct link to Plan Options") Without a saved plan file, `tofu apply` supports all planning modes and planning options available for `tofu plan`. * **[Planning Modes](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-modes) :** These include `-destroy`, which creates a plan to destroy all remote objects, and `-refresh-only`, which creates a plan to update OpenTofu state and root module output values. * **[Planning Options](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-options) :** These include specifying which resource instances OpenTofu should replace, setting OpenTofu input variables, etc. ### Apply Options[​](https://opentofu.org/docs/v1.10/cli/commands/apply/#apply-options "Direct link to Apply Options") The following options change how the apply command executes and reports on the apply operation. * `-auto-approve` - Skips interactive approval of plan before applying. This option is ignored when you pass a previously-saved plan file, because OpenTofu considers you passing the plan file as the approval and so will never prompt in that case. * `-compact-warnings` - Shows any warning messages in a compact form which includes only the summary messages, unless the warnings are accompanied by at least one error and thus the warning text might be useful context for the errors. * `-consolidate-warnings` - If OpenTofu produces any warnings, do not attempt to consolidate similar messages. All locations for all warnings will be listed. * `-consolidate-errors` - If OpenTofu produces any errors, attempt to consolidate similar messages into a single item. * `-input=false` - Disables all of OpenTofu's interactive prompts. Note that this also prevents OpenTofu from prompting for interactive approval of a plan, so OpenTofu will conservatively assume that you do not wish to apply the plan, causing the operation to fail. * `-json` - Enables the [machine readable JSON UI](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/) output. This implies `-input=false`, so the configuration must have no unassigned variable values to continue. To enable this flag, you must also either enable the `-auto-approve` flag or specify a previously-saved plan. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * `-no-color` - Disables terminal formatting sequences in the output. Use this if you are running OpenTofu in a context where its output will be rendered by a system that cannot interpret terminal formatting. * `-concise` - Disables progress-related messages in the output. * `-parallelism=n` - Limit the number of concurrent operation as OpenTofu [walks the graph](https://opentofu.org/docs/v1.10/internals/graph/#walking-the-graph) . Defaults to 10. * `-show-sensitive` - If specified, sensitive values will not be redacted in te UI output. * `-deprecation` - Specify what type of warnings are shown. Accepted values: "module:all", "module:local", "module:none". Default: module:all. When "module:all" is selected, OpenTofu will show the deprecation warnings for all modules. When "module:local" is selected, the warnings will be shown only for the modules that are imported with a relative path. When "module:none" is selected, all the deprecation warnings will be dropped. * All [planning modes](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-modes) and [planning options](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-options) for `tofu plan` - Customize how OpenTofu will create the plan. Only available when you run `tofu apply` without a saved plan file. For configurations using [the `local` backend](https://opentofu.org/docs/v1.10/language/settings/backends/local/) only, `tofu apply` also accepts the legacy options [`-state`, `-state-out`, and `-backup`](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) . ### Environment variables[​](https://opentofu.org/docs/v1.10/cli/commands/apply/#environment-variables "Direct link to Environment variables") You can further customize behavior of `apply` command by using [environment variables](https://opentofu.org/docs/v1.10/cli/config/environment-variables/) . For example, the [TF\_STATE\_PERSIST\_INTERVAL](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_state_persist_interval) environment variable allows to specify the interval between state persistence. Passing a Different Configuration Directory[​](https://opentofu.org/docs/v1.10/cli/commands/apply/#passing-a-different-configuration-directory "Direct link to Passing a Different Configuration Directory") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If your workflow relies on overriding the root module directory, use [the `-chdir` global option](https://opentofu.org/docs/v1.10/#switching-working-directory-with-chdir) instead, which works across all commands and makes OpenTofu consistently look in the given directory for all files it would normally read or write in the current working directory. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/apply/#usage) * [Automatic Plan Mode](https://opentofu.org/docs/v1.10/cli/commands/apply/#automatic-plan-mode) * [Saved Plan Mode](https://opentofu.org/docs/v1.10/cli/commands/apply/#saved-plan-mode) * [Plan Options](https://opentofu.org/docs/v1.10/cli/commands/apply/#plan-options) * [Apply Options](https://opentofu.org/docs/v1.10/cli/commands/apply/#apply-options) * [Environment variables](https://opentofu.org/docs/v1.10/cli/commands/apply/#environment-variables) * [Passing a Different Configuration Directory](https://opentofu.org/docs/v1.10/cli/commands/apply/#passing-a-different-configuration-directory) --- # Command: get | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/get/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: get ============ The `tofu get` command is used to download and update [modules](https://opentofu.org/docs/v1.10/language/modules/develop/) mentioned in the root module. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/get/#usage "Direct link to Usage") ----------------------------------------------------------------------------------------- Usage: `tofu get [options]` The modules are downloaded into a `.terraform` subdirectory of the current working directory. Don't commit this directory to your version control repository. Note Use of [variables in module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu get`. The `get` command supports the following option: * `-update` - If specified, modules that are already downloaded will be checked for updates and the updates will be downloaded if present. * `-no-color` - Disable text coloring in the output. * `-json` Produce output in a machine-readable JSON format, suitable for use in text editor integrations and other automated systems. Always disables color. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/get/#usage) --- # Command: console | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/console/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: console ================ The `tofu console` command provides an interactive console for evaluating [expressions](https://opentofu.org/docs/v1.10/language/expressions/) . Warning The `tofu console` command is not designed for use in scripts. You can use it, but you may find that some functions don't work as intended. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/console/#usage "Direct link to Usage") --------------------------------------------------------------------------------------------- Usage: `tofu console [options]` This command provides an interactive command-line console for evaluating and experimenting with [expressions](https://opentofu.org/docs/v1.10/language/expressions/) . You can use it to test interpolations before using them in configurations and to interact with any values currently saved in [state](https://opentofu.org/docs/v1.10/language/state/) . If the current state is empty or has not yet been created, you can use the console to experiment with the expression syntax and [built-in functions](https://opentofu.org/docs/v1.10/language/functions/) . The console holds a [lock on the state](https://opentofu.org/docs/v1.10/language/state/locking/) , and you will not be able to use the console while performing other actions that modify state. To close the console, enter the `exit` command or press Control-C or Control-D. For configurations using [the `local` backend](https://opentofu.org/docs/v1.10/language/settings/backends/local/) only, `tofu console` accepts the legacy command line option [`-state`](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) . Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu console`. This command also accepts the following options for tofu console: * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/console/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. Remote State[​](https://opentofu.org/docs/v1.10/cli/commands/console/#remote-state "Direct link to Remote State") ------------------------------------------------------------------------------------------------------------------ If [remote state](https://opentofu.org/docs/v1.10/language/state/remote/) is used by the current backend, OpenTofu will read the state for the current workspace from the backend before evaluating any expressions. Examples[​](https://opentofu.org/docs/v1.10/cli/commands/console/#examples "Direct link to Examples") ------------------------------------------------------------------------------------------------------ The `tofu console` command will read the OpenTofu configuration in the current working directory and the OpenTofu state file from the configured backend so that interpolations can be tested against both the values in the configuration and the state file. With the following `main.tf`: Code Block variable "apps" { type = map(any) default = { "foo" = { "region" = "us-east-1", }, "bar" = { "region" = "eu-west-1", }, "baz" = { "region" = "ap-south-1", }, }}resource "random_pet" "example" { for_each = var.apps} Executing `tofu console` will drop you into an interactive shell where you can test interpolations to: Print a value from a map: Code Block > var.apps.foo{ "region" = "us-east-1"} Filter a map based on a specific value: Code Block > { for key, value in var.apps : key => value if value.region == "us-east-1" }{ "foo" = { "region" = "us-east-1" }} Check if certain values may not be known until apply: Code Block > random_pet.example(known after apply) Test various functions: Code Block > cidrnetmask("172.16.0.0/12")"255.240.0.0" * [Usage](https://opentofu.org/docs/v1.10/cli/commands/console/#usage) * [Remote State](https://opentofu.org/docs/v1.10/cli/commands/console/#remote-state) * [Examples](https://opentofu.org/docs/v1.10/cli/commands/console/#examples) --- # Command: login | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/login/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: login ============== The `tofu login` command can be used to automatically obtain and save an API token for any host that offers OpenTofu-compatible services. Note This command is suitable only for use in interactive scenarios where it is possible to launch a web browser on the same host where OpenTofu is running. If you are running OpenTofu in an unattended automation scenario, you can [configure credentials manually in the CLI configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials) . Usage[​](https://opentofu.org/docs/v1.10/cli/commands/login/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------- Usage: `tofu login [hostname]` Credentials Storage[​](https://opentofu.org/docs/v1.10/cli/commands/login/#credentials-storage "Direct link to Credentials Storage") ------------------------------------------------------------------------------------------------------------------------------------- By default, OpenTofu will obtain an API token and save it in plain text in a local CLI configuration file called `credentials.tfrc.json`. When you run `tofu login`, it will explain specifically where it intends to save the API token and give you a chance to cancel if the current configuration is not as desired. If you don't wish to store your API token in the default location, you can optionally configure a [credentials helper program](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials-helpers) which knows how to store and later retrieve credentials in some other system, such as your organization's existing secrets management system. Login Server Support[​](https://opentofu.org/docs/v1.10/cli/commands/login/#login-server-support "Direct link to Login Server Support") ---------------------------------------------------------------------------------------------------------------------------------------- The `tofu login` command works with any server supporting the [login protocol](https://opentofu.org/docs/v1.10/internals/login-protocol/) . * [Usage](https://opentofu.org/docs/v1.10/cli/commands/login/#usage) * [Credentials Storage](https://opentofu.org/docs/v1.10/cli/commands/login/#credentials-storage) * [Login Server Support](https://opentofu.org/docs/v1.10/cli/commands/login/#login-server-support) --- # CLI Configuration | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/config/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) CLI Configuration ================= OpenTofu CLI can be configured with some global settings, which are separate from any OpenTofu configuration and which apply across all working directories. We've designed OpenTofu such that an average user running OpenTofu CLI interactively will not need to interact with any of these settings. As a result, most of the global settings relate to advanced or automated workflows, or unusual environmental conditions like running OpenTofu on an airgapped instance. * The [CLI config file](https://opentofu.org/docs/v1.10/cli/config/config-file/) configures provider installation and security features. * Several [environment variables](https://opentofu.org/docs/v1.10/cli/config/environment-variables/) can configure OpenTofu's inputs and outputs; this includes some alternate ways to provide information that is usually passed on the command line or read from the state of the shell. --- # Command: logout | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/logout/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: logout =============== The `tofu logout` command is used to remove credentials stored by `tofu login`. These credentials are API tokens for any host that offers OpenTofu-compatible services. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/logout/#usage "Direct link to Usage") -------------------------------------------------------------------------------------------- Usage: `tofu logout [hostname]` Note The API token is only removed from local storage, not destroyed on the remote server, so it will remain valid until manually revoked. Credentials Storage[​](https://opentofu.org/docs/v1.10/cli/commands/logout/#credentials-storage "Direct link to Credentials Storage") -------------------------------------------------------------------------------------------------------------------------------------- By default, OpenTofu will remove the token stored in plain text in a local CLI configuration file called `credentials.tfrc.json`. If you have configured a [credentials helper program](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials-helpers) , OpenTofu will use the helper's `forget` command to remove it. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/logout/#usage) * [Credentials Storage](https://opentofu.org/docs/v1.10/cli/commands/logout/#credentials-storage) --- # Command: graph | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/graph/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: graph ============== The `tofu graph` command is used to generate a visual representation of either a configuration or execution plan. The output is in the DOT format, which can be used by [GraphViz](http://www.graphviz.org/) to generate charts. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/graph/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------- Usage: `tofu graph [options]` Outputs the visual execution graph of OpenTofu resources according to either the current configuration or an execution plan. The graph is outputted in DOT format. The typical program that can read this format is GraphViz, but many web services are also available to read this format. The `-type` flag can be used to control the type of graph shown. OpenTofu creates different graphs for different operations. See the options below for the list of types supported. The default type is "plan" if a configuration is given, and "apply" if a plan file is passed as an argument. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu graph`. Options: * `-plan=tfplan` - Render graph using the specified plan file instead of the configuration in the current directory. * `-draw-cycles` - Highlight any cycles in the graph with colored edges. This helps when diagnosing cycle errors. * `-type=plan` - Type of graph to output. Can be: `plan`, `plan-refresh-only`, `plan-destroy`, or `apply`. * `-module-depth=n` - (deprecated) In prior versions of OpenTofu, specified the depth of modules to show in the output. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. Generating Images[​](https://opentofu.org/docs/v1.10/cli/commands/graph/#generating-images "Direct link to Generating Images") ------------------------------------------------------------------------------------------------------------------------------- The output of `tofu graph` is in the DOT format, which can easily be converted to an image by making use of `dot` provided by GraphViz: Code Block $ tofu graph | dot -Tsvg > graph.svg Here is an example graph output: ![Graph Example](https://opentofu.org/assets/images/graph-example-2cb670610fca15c115d0e2432c41a241.png) * [Usage](https://opentofu.org/docs/v1.10/cli/commands/graph/#usage) * [Generating Images](https://opentofu.org/docs/v1.10/cli/commands/graph/#generating-images) --- # Command: providers | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/providers/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: providers ================== The `tofu providers` command shows information about the [provider requirements](https://opentofu.org/docs/v1.10/language/providers/requirements/) of the configuration in the current working directory, as an aid to understanding where each requirement was detected from. This command also has several subcommands with different purposes. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/providers/#usage "Direct link to Usage") ----------------------------------------------------------------------------------------------- Usage: `tofu providers [options]` Code Block $ tofu providersProviders required by configuration:.└── module.submodule β”œβ”€β”€ provider[registry.opentofu.org/hashicorp/tfcoremock] └── module.nestedProviders required by state: provider[registry.opentofu.org/hashicorp/tfcoremock] Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu providers`. This command accepts the following options: * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/providers/#usage) --- # Command: providers mirror | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/providers/mirror/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: providers mirror ========================= The `tofu providers mirror` command downloads the providers required for the current configuration and copies them into a directory in the local filesystem. In normal use, `tofu init` will automatically download needed providers from provider registries as part of initializing the current working directory. Sometimes OpenTofu is running in an environment where that isn't possible, such as on an isolated network without access to an OpenTofu Registry. In that case, [explicit installation method configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#explicit-installation-method-configuration) allows you to configure OpenTofu, when running on a particular system, to consult only a local filesystem directory where you've created a local mirror of the necessary plugins, and to skip accessing the upstream registry at all. The `tofu providers mirror` command can automatically populate a directory that will be used as a local filesystem mirror in the provider installation configuration. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/providers/mirror/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------------ Usage: `tofu providers mirror [options] ` A single target directory is required. OpenTofu will create under that directory the path structure that is expected for filesystem-based provider plugin mirrors, populating it with `.zip` files containing the plugins themselves. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu providers mirror`. This command accepts the following generic options: * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. OpenTofu will also generate various `.json` index files which contain suitable responses to implement [the network mirror protocol](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/) , if you upload the resulting directory to a static website host. OpenTofu ignores those index files when using the directory as a filesystem mirror, because the directory entries themselves are authoritative in that case. This command supports the following additional options: * `-platform=OS_ARCH` - Choose which target platform to build a mirror for. By default OpenTofu will obtain plugin packages suitable for the platform where you run this command. Use this flag multiple times to include packages for multiple target systems. Target platform names consist of an operating system and a CPU architecture. For example, `linux_amd64` selects the Linux operating system running on an AMD64 or x86\_64 CPU. You can run `tofu providers mirror` again on an existing mirror directory to update it with new packages. For example, you can add packages for a new target platform by re-running the command with the desired new `-platform=...` option, and it will place the packages for that new platform without removing packages you previously downloaded, merging the resulting set of packages together to update the JSON index files. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/providers/mirror/#usage) --- # Resource Importability | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/import/importability/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Resource Importability ====================== Each resource in OpenTofu must implement some basic logic to become importable. As a result, you cannot import all OpenTofu resources. Please reference the provider's specific documentation on which resources can be imported. If you have issues importing a resource, report an issue in the relevant provider repository. OpenTofu supports all providers through the Terraform Plugin SDK. To make a resource importable, refer to the [Terraform Plugin SDK Documentation](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/import) . --- # Initializing Working Directories | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/init/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Initializing Working Directories ================================ OpenTofu expects to be invoked from a working directory that contains configuration files written in [the OpenTofu language](https://opentofu.org/docs/v1.10/language/) . OpenTofu uses configuration content from this directory, and also uses the directory to store settings, cached plugins and modules, and sometimes state data. A working directory must be initialized before OpenTofu can perform any operations in it (like provisioning infrastructure or modifying state). Working Directory Contents[​](https://opentofu.org/docs/v1.10/cli/init/#working-directory-contents "Direct link to Working Directory Contents") ------------------------------------------------------------------------------------------------------------------------------------------------ A OpenTofu working directory typically contains: * A OpenTofu configuration describing resources OpenTofu should manage. This configuration is expected to change over time. * A hidden `.terraform` directory, which OpenTofu uses to manage cached provider plugins and modules, record which [workspace](https://opentofu.org/docs/v1.10/cli/workspaces/) is currently active, and record the last known backend configuration in case it needs to migrate state on the next run. This directory is automatically managed by OpenTofu, and is created during initialization. * State data, if the configuration uses the default `local` backend. This is managed by OpenTofu in a `terraform.tfstate` file (if the directory only uses the default workspace) or a `terraform.tfstate.d` directory (if the directory uses multiple workspaces). Initialization[​](https://opentofu.org/docs/v1.10/cli/init/#initialization "Direct link to Initialization") ------------------------------------------------------------------------------------------------------------ Run the `tofu init` command to initialize a working directory that contains a OpenTofu configuration. After initialization, you will be able to perform other commands, like `tofu plan` and `tofu apply`. If you try to run a command that relies on initialization without first initializing, the command will fail with an error and explain that you need to run init. Initialization performs several tasks to prepare a directory, including accessing state in the configured backend, downloading and installing provider plugins, and downloading modules. Under some conditions (usually when changing from one backend to another), it might ask the user for guidance or confirmation. For details, see [the `tofu init` command](https://opentofu.org/docs/v1.10/cli/commands/init/) . Reinitialization[​](https://opentofu.org/docs/v1.10/cli/init/#reinitialization "Direct link to Reinitialization") ------------------------------------------------------------------------------------------------------------------ Certain types of changes to a OpenTofu configuration can require reinitialization before normal operations can continue. This includes changes to provider requirements, module sources or version constraints, and backend configurations. You can reinitialize a directory by running `tofu init` again. In fact, you can reinitialize at any time; the init command is idempotent, and will have no effect if no changes are required. If reinitialization is required, any commands that rely on initialization will fail with an error and tell you so. Reinitializing Only Modules[​](https://opentofu.org/docs/v1.10/cli/init/#reinitializing-only-modules "Direct link to Reinitializing Only Modules") --------------------------------------------------------------------------------------------------------------------------------------------------- The `tofu get` command will download modules referenced in the configuration, but will not perform the other required initialization tasks. This command is only useful for niche workflows, and most OpenTofu users can ignore it in favor of `tofu init`. * [Working Directory Contents](https://opentofu.org/docs/v1.10/cli/init/#working-directory-contents) * [Initialization](https://opentofu.org/docs/v1.10/cli/init/#initialization) * [Reinitialization](https://opentofu.org/docs/v1.10/cli/init/#reinitialization) * [Reinitializing Only Modules](https://opentofu.org/docs/v1.10/cli/init/#reinitializing-only-modules) --- # Import | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/import/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Import ====== OpenTofu can import existing infrastructure resources. This functionality lets you bring existing resources under OpenTofu management. Note OpenTofu supports `import` blocks. Unlike the `tofu import` command, you can use `import` blocks to import more than one resource at a time, and you can review imports as part of your normal plan and apply workflow. [Learn more about `import` blocks](https://opentofu.org/docs/v1.10/language/import/) . State Only[​](https://opentofu.org/docs/v1.10/cli/import/#state-only "Direct link to State Only") -------------------------------------------------------------------------------------------------- Warning OpenTofu expects that each remote object is bound to a _single_ resource address. You should import each remote object to _one_ OpenTofu resource address. If you import the same object multiple times, OpenTofu may exhibit unwanted behavior. See [State](https://opentofu.org/docs/v1.10/language/state/) for more details. The `tofu import` CLI command can only import resources into the [state](https://opentofu.org/docs/v1.10/language/state/) . Importing via the CLI does _not_ generate configuration. If you want to generate the accompanying configuration for imported resources, [use the `import` block instead](https://opentofu.org/docs/v1.10/language/import/) . Before you run `tofu import` you must manually write a `resource` configuration block for the resource. The resource block describes where OpenTofu should map the imported object. Cloud Backend[​](https://opentofu.org/docs/v1.10/cli/import/#cloud-backend "Direct link to Cloud Backend") ----------------------------------------------------------------------------------------------------------- When you use OpenTofu on the command line with a cloud backend, many commands like `apply` run inside your cloud backend's environment. However, the `import` command runs locally, so it does not have access to information from the cloud backend. To successfully perform an import, you may need to set local variables equivalent to any remote workspace variables in the cloud backend. * [State Only](https://opentofu.org/docs/v1.10/cli/import/#state-only) * [Cloud Backend](https://opentofu.org/docs/v1.10/cli/import/#cloud-backend) --- # Inspecting Infrastructure | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/inspect/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Inspecting Infrastructure ========================= OpenTofu configurations and state data include some highly structured information about the resources they manage; this includes dependency information, outputs (which are pieces of generated or discovered data that the configuration's author considers important enough to surface to users), and more. OpenTofu CLI includes some commands for inspecting or transforming this data. You can use these to integrate other tools with OpenTofu's infrastructure data, or just to gain a deeper or more holistic understanding of your infrastructure. * [The `tofu graph` command](https://opentofu.org/docs/v1.10/cli/commands/graph/) creates a visual representation of a configuration or a set of planned changes. * [The `tofu output` command](https://opentofu.org/docs/v1.10/cli/commands/output/) can get the values for the top-level [output values](https://opentofu.org/docs/v1.10/language/values/outputs/) of a configuration, which are often helpful when making use of the infrastructure OpenTofu has provisioned. * [The `tofu show` command](https://opentofu.org/docs/v1.10/cli/commands/show/) can generate human-readable versions of a state file or plan file, or generate machine-readable versions that can be integrated with other tools. * [The `tofu state list` command](https://opentofu.org/docs/v1.10/cli/commands/state/list/) can list the resources being managed by the current working directory and workspace, providing a complete or filtered list. * [The `tofu state show` command](https://opentofu.org/docs/v1.10/cli/commands/state/show/) can print all of the attributes of a given resource being managed by the current working directory and workspace, including generated read-only attributes like the unique ID assigned by the cloud provider. --- # Command: output | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/output/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: output =============== The `tofu output` command is used to extract the value of an output variable from the state file. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/output/#usage "Direct link to Usage") -------------------------------------------------------------------------------------------- Usage: `tofu output [options] [NAME]` With no additional arguments, `output` will display all the outputs for the root module. If an output `NAME` is specified, only the value of that output is printed. Note Use of variables in [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu output`. The command-line flags are all optional. The following flags are available: * `-json` - If specified, the outputs are formatted as a JSON object, with a key per output. If `NAME` is specified, only the output specified will be returned. This can be piped into tools such as `jq` for further processing. * `-raw` - If specified, OpenTofu will convert the specified output value to a string and print that string directly to the output, without any special formatting. This can be convenient when working with shell scripts, but it only supports string, number, and boolean values. Use `-json` instead for processing complex data types. * `-no-color` - If specified, output won't contain any color. * `-state=path` - Path to the state file. Defaults to "terraform.tfstate". Ignored when [remote state](https://opentofu.org/docs/v1.10/language/state/remote/) is used. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. * `-show-sensitive` - If specified, sensitive values will be displayed. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. Note When using the `-json` or `-raw` command-line flag, any sensitive values in OpenTofu state will be displayed in plain text. For more information, see [Sensitive Data in State](https://opentofu.org/docs/v1.10/language/state/sensitive-data/) . Examples[​](https://opentofu.org/docs/v1.10/cli/commands/output/#examples "Direct link to Examples") ----------------------------------------------------------------------------------------------------- These examples assume the following OpenTofu output snippet. Code Block output "instance_ips" { value = aws_instance.web.*.public_ip}output "lb_address" { value = aws_alb.web.public_dns}output "password" { sensitive = true value = var.secret_password} To list all outputs: Code Block $ tofu outputinstance_ips = [ "54.43.114.12", "52.122.13.4", "52.4.116.53"]lb_address = "my-app-alb-1657023003.us-east-1.elb.amazonaws.com"password = Note that outputs with the `sensitive` attribute will be redacted: Code Block $ tofu output passwordpassword = To query for the DNS address of the load balancer: Code Block $ tofu output lb_address"my-app-alb-1657023003.us-east-1.elb.amazonaws.com" To query for all instance IP addresses: Code Block $ tofu output instance_ipsinstance_ips = [ "54.43.114.12", "52.122.13.4", "52.4.116.53"] Use in automation[​](https://opentofu.org/docs/v1.10/cli/commands/output/#use-in-automation "Direct link to Use in automation") -------------------------------------------------------------------------------------------------------------------------------- The `tofu output` command by default displays in a human-readable format, which can change over time to improve clarity. For scripting and automation, use `-json` to produce the stable JSON format. You can parse the output using a JSON command-line parser such as [jq](https://stedolan.github.io/jq/) : Code Block $ tofu output -json instance_ips | jq -r '.[0]'54.43.114.12 For the common case of directly using a string value in a shell script, you can use `-raw` instead, which will print the string directly with no extra escaping or whitespace. Code Block $ tofu output -raw lb_addressmy-app-alb-1657023003.us-east-1.elb.amazonaws.com The `-raw` option works only with values that OpenTofu can automatically convert to strings. Use `-json` instead, possibly combined with `jq`, to work with complex-typed values such as objects. OpenTofu strings are sequences of Unicode characters rather than raw bytes, so the `-raw` output will be UTF-8 encoded when it contains non-ASCII characters. If you need a different character encoding, use a separate command such as `iconv` to transcode OpenTofu's raw output. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/output/#usage) * [Examples](https://opentofu.org/docs/v1.10/cli/commands/output/#examples) * [Use in automation](https://opentofu.org/docs/v1.10/cli/commands/output/#use-in-automation) --- # Command: init | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/init/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: init ============= The `tofu init` command initializes a working directory containing OpenTofu configuration files. This is the first command that should be run after writing a new OpenTofu configuration or cloning an existing one from version control. It is safe to run this command multiple times. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/init/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------ Usage: `tofu init [options]` This command performs several different initialization steps in order to prepare the current working directory for use with OpenTofu. More details on these are in the sections below, but in most cases it is not necessary to worry about these individual steps. This command is always safe to run multiple times, to bring the working directory up to date with changes in the configuration. Though subsequent runs may give errors, this command will never delete your existing configuration or state. This command requires value assignment for variables used in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) and [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) blocks. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. General Options[​](https://opentofu.org/docs/v1.10/cli/commands/init/#general-options "Direct link to General Options") ------------------------------------------------------------------------------------------------------------------------ The following options apply to all of (or several of) the initialization steps: * `-input=true` Ask for input if necessary. If false, will error if input was required. * `-lock=false` Disable locking of state files during state-related operations. * `-lock-timeout=` Override the time OpenTofu will wait to acquire a state lock. The default is `0s` (zero seconds), which causes immediate failure if the lock is already held by another process. * `-no-color` Disable color codes in the command output. * `-upgrade` Opt to upgrade modules and plugins as part of their respective installation steps. See the sections below for more details. * `-json` Produce output in a machine-readable JSON format, suitable for use in text editor integrations and other automated systems. Always disables color. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. Copy a Source Module[​](https://opentofu.org/docs/v1.10/cli/commands/init/#copy-a-source-module "Direct link to Copy a Source Module") --------------------------------------------------------------------------------------------------------------------------------------- By default, `tofu init` assumes that the working directory already contains a configuration and will attempt to initialize that configuration. Optionally, init can be run against an empty directory with the `-from-module=MODULE-SOURCE` option, in which case the given module will be copied into the target directory before any other initialization steps are run. This special mode of operation supports two use-cases: * Given a version control source, it can serve as a shorthand for checking out a configuration from version control and then initializing the working directory for it. * If the source refers to an _example_ configuration, it can be copied into a local directory to be used as a basis for a new configuration. For routine use it is recommended to check out configuration from version control separately, using the version control system's own commands. This way it is possible to pass extra flags to the version control system when necessary, and to perform other preparation steps (such as configuration generation, or activating credentials) before running `tofu init`. Backend Initialization[​](https://opentofu.org/docs/v1.10/cli/commands/init/#backend-initialization "Direct link to Backend Initialization") --------------------------------------------------------------------------------------------------------------------------------------------- During init, the root configuration directory is consulted for [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) and the chosen backend is initialized using the given configuration settings. Note Use of [variables in the backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) block requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu init`. Re-running init with an already-initialized backend will update the working directory to use the new backend settings. Either `-reconfigure` or `-migrate-state` must be supplied to update the backend configuration. The `-migrate-state` option will attempt to copy existing state to the new backend, and depending on what changed, may result in interactive prompts to confirm migration of workspace states. The `-force-copy` option suppresses these prompts and answers "yes" to the migration questions. Enabling `-force-copy` also automatically enables the `-migrate-state` option. The `-reconfigure` option disregards any existing configuration, preventing migration of any existing state. To skip backend configuration, use `-backend=false`. Note that some other init steps require an initialized backend, so it is recommended to use this flag only when the working directory was already previously initialized for a particular backend. The `-backend-config=...` option can be used for [partial backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#partial-configuration) , in situations where the backend settings are dynamic or sensitive and so cannot be statically specified in the configuration file. Child Module Installation[​](https://opentofu.org/docs/v1.10/cli/commands/init/#child-module-installation "Direct link to Child Module Installation") ------------------------------------------------------------------------------------------------------------------------------------------------------ During init, the configuration is searched for `module` blocks, and the source code for referenced [modules](https://opentofu.org/docs/v1.10/language/modules/develop/) is retrieved from the locations given in their `source` arguments. Re-running init with modules already installed will install the sources for any modules that were added to configuration since the last init, but will not change any already-installed modules. Use `-upgrade` to override this behavior, updating all modules to the latest available source code. To skip child module installation, use `-get=false`. Note that some other init steps can complete only when the module tree is complete, so it's recommended to use this flag only when the working directory was already previously initialized with its child modules. Plugin Installation[​](https://opentofu.org/docs/v1.10/cli/commands/init/#plugin-installation "Direct link to Plugin Installation") ------------------------------------------------------------------------------------------------------------------------------------ Most OpenTofu providers are published separately from OpenTofu as plugins. During init, OpenTofu searches the configuration for both direct and indirect references to providers and attempts to install the plugins for those providers. For providers that are published in either [the public OpenTofu Registry](https://registry.opentofu.org/) or in a third-party provider registry, `tofu init` will automatically find, download, and install the necessary provider plugins. If you cannot or do not wish to install providers from their origin registries, you can customize how OpenTofu installs providers using [the provider installation settings in the CLI configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation) . For more information about specifying which providers are required for each of your modules, see [Provider Requirements](https://opentofu.org/docs/v1.10/language/providers/requirements/) . After successful installation, OpenTofu writes information about the selected providers to [the dependency lock file](https://opentofu.org/docs/v1.10/language/files/dependency-lock/) . You should commit this file to your version control system to ensure that when you run `tofu init` again in future OpenTofu will select exactly the same provider versions. Use the `-upgrade` option if you want OpenTofu to ignore the dependency lock file and consider installing newer versions. You can modify `tofu init`'s plugin behavior with the following options: * `-upgrade` Upgrade all previously-selected plugins to the newest version that complies with the configuration's version constraints. This will cause OpenTofu to ignore any selections recorded in the dependency lock file, and to take the newest available version matching the configured version constraints. * `-plugin-dir=PATH` β€”Β Force plugin installation to read plugins _only_ from the specified directory, as if it had been configured as a `filesystem_mirror` in the CLI configuration. If you intend to routinely use a particular filesystem mirror then we recommend [configuring OpenTofu's installation methods globally](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation) . You can use `-plugin-dir` as a one-time override for exceptional situations, such as if you are testing a local build of a provider plugin you are currently developing. * `-lockfile=MODE` Set a dependency lockfile mode. The valid values for the lockfile mode are as follows: * `readonly`: suppress the lockfile changes, but verify checksums against the information already recorded. It conflicts with the `-upgrade` flag. If you update the lockfile with third-party dependency management tools, it would be useful to control when it changes explicitly. Running `tofu init` in automation[​](https://opentofu.org/docs/v1.10/cli/commands/init/#running-tofu-init-in-automation "Direct link to running-tofu-init-in-automation") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- For teams that use OpenTofu as a key part of a change management and deployment pipeline, it can be desirable to orchestrate OpenTofu runs in some sort of automation in order to ensure consistency between runs, and provide other interesting features such as integration with version control hooks. There are some special concerns when running `init` in such an environment, including optionally making plugins available locally to avoid repeated re-installation. Passing a Different Configuration Directory[​](https://opentofu.org/docs/v1.10/cli/commands/init/#passing-a-different-configuration-directory "Direct link to Passing a Different Configuration Directory") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ If your workflow relies on overriding the root module directory, use [the `-chdir` global option](https://opentofu.org/docs/v1.10/cli/commands/#switching-working-directory-with-chdir) instead, which works across all commands and makes OpenTofu consistently look in the given directory for all files it would normally read or write in the current working directory. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/init/#usage) * [General Options](https://opentofu.org/docs/v1.10/cli/commands/init/#general-options) * [Copy a Source Module](https://opentofu.org/docs/v1.10/cli/commands/init/#copy-a-source-module) * [Backend Initialization](https://opentofu.org/docs/v1.10/cli/commands/init/#backend-initialization) * [Child Module Installation](https://opentofu.org/docs/v1.10/cli/commands/init/#child-module-installation) * [Plugin Installation](https://opentofu.org/docs/v1.10/cli/commands/init/#plugin-installation) * [Running `tofu init` in automation](https://opentofu.org/docs/v1.10/cli/commands/init/#running-tofu-init-in-automation) * [Passing a Different Configuration Directory](https://opentofu.org/docs/v1.10/cli/commands/init/#passing-a-different-configuration-directory) --- # Command: providers lock | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/providers/lock/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: providers lock ======================= The `tofu providers lock` consults upstream registries (by default) in order to write provider dependency information into [the dependency lock file](https://opentofu.org/docs/v1.10/language/files/dependency-lock/) . The common way to update the dependency lock file is as a side-effect of normal provider installation during [`tofu init`](https://opentofu.org/docs/v1.10/cli/commands/init/) , but there are several situations where that automatic approach may not be sufficient: * If you are running OpenTofu in an environment that uses [alternative provider installation methods](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation) , such as filesystem or network mirrors, normal provider installation will not access the origin registry for a provider and therefore OpenTofu will not be able to populate all of the possible package checksums for the selected provider versions. If you use `tofu lock` to write the official release checksums for a provider into the dependency lock file then future `tofu init` runs will verify the packages available in your selected mirror against the official checksums previously recorded, giving additional certainty that the mirror is serving the provider packages it is claiming to. * If your team runs OpenTofu across a number of different platforms (e.g. on both Windows and Linux) and the upstream registry for a provider is unable to provide signed checksums using the latest hashing scheme, subsequent runs of OpenTofu on other platforms may [add additional checksums to the lock file](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#new-provider-package-checksums) . You can avoid that by pre-populating hashes for all of the platforms you intend to use, using the `tofu providers lock` command. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/providers/lock/#usage "Direct link to Usage") ---------------------------------------------------------------------------------------------------- Usage: `tofu providers lock [options] [providers...]` Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu providers lock`. This command accepts the following generic options: * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. With no additional command line arguments, `tofu providers lock` will analyze the configuration in the current working directory to find all of the providers it depends on, and it will fetch the necessary data about those providers from their origin registries and then update [the dependency lock file](https://opentofu.org/docs/v1.10/language/files/dependency-lock/) to include a selected version for each provider and all of the package checksums that are covered by the provider developer's cryptographic signature. Warning The `tofu providers lock` command prints information about what it has fetched and whether each package was signed using a cryptographic signature, but it cannot automatically verify that the providers are trustworthy and that they comply with your local system policies or relevant regulations. Review the signing key information in the output to confirm that you trust all of the signers before committing the updated lock file to your version control system. If you list one or more provider source addresses on the command line then `tofu providers lock` will restrict its work only to those providers, leaving the lock entries for other providers (if any) unchanged. You can customize the default behavior using the following additional option: * `-fs-mirror=PATH` - Direct OpenTofu to look for provider packages in the given local filesystem mirror directory, instead of in upstream registries. The given directory must use the usual filesystem mirror directory layout. * `-net-mirror=URL` - Direct OpenTofu to look for provider packages in the given network mirror service, instead of in upstream registries. The given URL must implement [the OpenTofu provider network mirror protocol](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/) . * `-platform=OS_ARCH` - Specify a platform you intend to use to work with this OpenTofu configuration. OpenTofu will ensure that the providers are all available for the given platform and will save enough package checksums in the lock file to support _at least_ the specified platforms. Use this option multiple times to include checksums for multiple target systems. Target platform names consist of an operating system and a CPU architecture. For example, `linux_amd64` selects the Linux operating system running on an AMD64 or x86\_64 CPU. There is more detail on this option in the following section. Specifying Target Platforms[​](https://opentofu.org/docs/v1.10/cli/commands/providers/lock/#specifying-target-platforms "Direct link to Specifying Target Platforms") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- In your environment you may, for example, have both developers who work with your OpenTofu configuration on their Windows or macOS workstations _and_ automated systems that apply the configuration while running on Linux. In that situation, you could choose to verify that all of your providers support all of those platforms, and to pre-populate the lock file with the necessary checksums, by running `tofu providers lock` and specifying those three platforms: Code Block tofu providers lock \ -platform=windows_amd64 \ # 64-bit Windows -platform=darwin_amd64 \ # 64-bit macOS -platform=linux_amd64 # 64-bit Linux (The above example uses Unix-style shell wrapping syntax for readability. If you are running the command on Windows then you will need to put all of the arguments on a single line, and remove the backslashes and comments.) Lock Entries for In-house Providers[​](https://opentofu.org/docs/v1.10/cli/commands/providers/lock/#lock-entries-for-in-house-providers "Direct link to Lock Entries for In-house Providers") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- An _in-house provider_ is one that isn't published on a real OpenTofu provider registry because it's developed and used only within a particular organization and distributed via either a filesystem mirror or network mirror. By default, `tofu providers lock` assumes all providers are available at a OpenTofu provider registry and tries to contact the origin registries in order to get access to the most detailed information about the provider packages. To create a lock entry for a particular provider that is available only in a local mirror, you can use either the `-fs-mirror` or `-net-mirror` command line options to override the default behavior of consulting the provider's origin registry: Code Block tofu providers lock \ -fs-mirror=/usr/local/tofu/providers -platform=windows_amd64 \ -platform=darwin_amd64 \ -platform=linux_amd64 \ tf.example.com/ourcompany/ourplatform (The above example uses Unix-style shell wrapping syntax for readability. If you are running the command on Windows then you will need to put all of the arguments on a single line, and remove the backslashes.) Because the command above includes the provider source address `tf.example.com/ourcompany/ourplatform`, `tofu providers lock` will only attempt to access that particular provider and will leave the lock entries for any other providers unchanged. If you have a variety of different providers available from different sources, you can run `tofu providers lock` multiple times and specify a different subset of your providers each time. The `-fs-mirror` and `-net-mirror` options have the same meaning as `filesystem_mirror` and `network_mirror` blocks in [the provider installation methods configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation) , but specify only a single method in order to be explicit about where you intend to derive the package checksum information from. Note that only an origin registry can provide official checksums covered by the original developer's cryptographic signature. Lock entries created from filesystem or network mirrors will therefore cover only the exact platforms you requested, and the recorded checksums will be those reported by the mirror, rather than the origin registry's official checksums. If you want to ensure that the recorded checksums are the ones signed by the original provider publisher, run this command _without_ either the `-fs-mirror` or `-net-mirror` options to fetch all information from origin registries. If you wish, you can publish your in-house providers via an in-house provider registry, which will then allow locking and installation of those providers without any special options or additional CLI configuration. For more information, see [the provider registry protocol](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/) . * [Usage](https://opentofu.org/docs/v1.10/cli/commands/providers/lock/#usage) * [Specifying Target Platforms](https://opentofu.org/docs/v1.10/cli/commands/providers/lock/#specifying-target-platforms) * [Lock Entries for In-house Providers](https://opentofu.org/docs/v1.10/cli/commands/providers/lock/#lock-entries-for-in-house-providers) --- # Command: providers schema | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: providers schema ========================= The `tofu providers schema` command is used to print detailed schemas for the providers used in the current configuration. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------------ Usage: `tofu providers schema [options]` Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu providers schema`. The following flags are available: * `-json` - Displays the schemas in a machine-readable, JSON format. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. Please note that, at this time, the `-json` flag is a _required_ option. In future releases, this command will be extended to allow for additional options. The output includes a `format_version` key, which has value `"1.0"`. The semantics of this version are: * We will increment the minor version, e.g. `"1.1"`, for backward-compatible changes or additions. Ignore any object properties with unrecognized names to remain forward-compatible with future minor versions. * We will increment the major version, e.g. `"2.0"`, for changes that are not backward-compatible. Reject any input which reports an unsupported major version. We will introduce new major versions only within the bounds of [the OpenTofu 1.0 Compatibility Promises](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/) . Format Summary[​](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#format-summary "Direct link to Format Summary") --------------------------------------------------------------------------------------------------------------------------------- The following sections describe the JSON output format by example, using a pseudo-JSON notation. Important elements are described with comments, which are prefixed with //. To avoid excessive repetition, we've split the complete format into several discrete sub-objects, described under separate headers. References wrapped in angle brackets (like ``) are placeholders which, in the real output, would be replaced by an instance of the specified sub-object. The JSON output format consists of the following objects and sub-objects: * [Providers Schema Representation](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#providers-schema-representation) - the top-level object returned by `tofu providers schema -json` * [Schema Representation](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#schema-representation) - a sub-object of providers, resources, and data sources that describes their schema * [Block Representation](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#block-representation) - a sub-object of schemas that describes attributes and nested blocks Providers Schema Representation[​](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#providers-schema-representation "Direct link to Providers Schema Representation") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Code Block { "format_version": "1.0", // "provider_schemas" describes the provider schemas for all // providers throughout the configuration tree. "provider_schemas": { // keys in this map are the provider type, such as "random" "example_provider_name": { // "provider" is the schema for the provider configuration "provider": , // "resource_schemas" map the resource type name to the resource's schema "resource_schemas": { "example_resource_name": }, // "data_source_schemas" map the data source type name to the // data source's schema "data_source_schemas": { "example_datasource_name": , } }, "example_provider_two": { … } }} Schema Representation[​](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#schema-representation "Direct link to Schema Representation") ------------------------------------------------------------------------------------------------------------------------------------------------------ A schema representation pairs a provider or resource schema (in a "block") with that schema's version. Code Block { // "version" is the schema version, not the provider version "version": int64, "block": } Block Representation[​](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#block-representation "Direct link to Block Representation") --------------------------------------------------------------------------------------------------------------------------------------------------- A block representation contains "attributes" and "block\_types" (which represent nested blocks). Code Block { // "attributes" describes any attributes that appear directly inside the // block. Keys in this map are the attribute names. "attributes": { "example_attribute_name": { // "type" is a representation of a type specification // that the attribute's value must conform to. "type": "string", // "description" is an English-language description of // the purpose and usage of the attribute. "description": "string", // "required", if set to true, specifies that an // omitted or null value is not permitted. "required": bool, // "optional", if set to true, specifies that an // omitted or null value is permitted. "optional": bool, // "computed", if set to true, indicates that the // value comes from the provider rather than the // configuration. "computed": bool, // "sensitive", if set to true, indicates that the // attribute may contain sensitive information. "sensitive": bool }, }, // "block_types" describes any nested blocks that appear directly // inside the block. // Keys in this map are the names of the block_type. "block_types": { "example_block_name": { // "nesting_mode" describes the nesting mode for the // child block, and can be one of the following: // single // list // set // map "nesting_mode": "list", "block": , // "min_items" and "max_items" set lower and upper // limits on the number of child blocks allowed for // the list and set modes. These are // omitted for other modes. "min_items": 1, "max_items": 3 }} * [Usage](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#usage) * [Format Summary](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#format-summary) * [Providers Schema Representation](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#providers-schema-representation) * [Schema Representation](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#schema-representation) * [Block Representation](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/#block-representation) --- # Command: state | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/state/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state ============== The `tofu state` command is used for advanced state management. As your OpenTofu usage becomes more advanced, there are some cases where you may need to modify the [OpenTofu state](https://opentofu.org/docs/v1.10/language/state/) . Rather than modify the state directly, the `tofu state` commands can be used in many cases instead. This command is a nested subcommand, meaning that it has further subcommands. These subcommands are listed to the left. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/state/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------- Usage: `tofu state [options] [args]` Please click a subcommand to the left for more information. Remote State[​](https://opentofu.org/docs/v1.10/cli/commands/state/#remote-state "Direct link to Remote State") ---------------------------------------------------------------------------------------------------------------- The OpenTofu state subcommands all work with remote state just as if it was local state. Reads and writes may take longer than normal as each read and each write do a full network roundtrip. Otherwise, backups are still written to disk and the CLI usage is the same as if it were local state. Backups[​](https://opentofu.org/docs/v1.10/cli/commands/state/#backups "Direct link to Backups") ------------------------------------------------------------------------------------------------- All `tofu state` subcommands that modify the state write backup files. The path of these backup file can be controlled with `-backup`. Subcommands that are read-only (such as [list](https://opentofu.org/docs/v1.10/cli/commands/state/list/) ) do not write any backup files since they aren't modifying the state. Note that backups for state modification _can not be disabled_. Due to the sensitivity of the state file, OpenTofu forces every state modification command to write a backup file. You'll have to remove these files manually if you don't want to keep them around. Command-Line Friendly[​](https://opentofu.org/docs/v1.10/cli/commands/state/#command-line-friendly "Direct link to Command-Line Friendly") ------------------------------------------------------------------------------------------------------------------------------------------- The output and command-line structure of the state subcommands is designed to be usable with Unix command-line tools such as grep, awk, and similar PowerShell commands. For advanced filtering and modification, we recommend piping OpenTofu state subcommands together with other command line tools. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/state/#usage) * [Remote State](https://opentofu.org/docs/v1.10/cli/commands/state/#remote-state) * [Backups](https://opentofu.org/docs/v1.10/cli/commands/state/#backups) * [Command-Line Friendly](https://opentofu.org/docs/v1.10/cli/commands/state/#command-line-friendly) --- # Environment Variables | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Environment Variables ===================== OpenTofu refers to a number of environment variables to customize various aspects of its behavior. None of these environment variables are required when using OpenTofu, but they can be used to change some of OpenTofu's default behaviors in unusual situations, or to increase output verbosity for debugging. TF\_LOG[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_log "Direct link to TF_LOG") ------------------------------------------------------------------------------------------------------------- Enables detailed logs to appear on stderr which is useful for debugging. For example: Code Block export TF_LOG=trace To disable, either unset it, or set it to `off`. For example: Code Block export TF_LOG=off For more on debugging OpenTofu, check out the section on [Debugging](https://opentofu.org/docs/v1.10/internals/debugging/) . TF\_LOG\_PATH[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_log_path "Direct link to TF_LOG_PATH") ----------------------------------------------------------------------------------------------------------------------------- This specifies where the log should persist its output to. Note that even when `TF_LOG_PATH` is set, `TF_LOG` must be set in order for any logging to be enabled. For example, to always write the log to the directory you're currently running tofu from: Code Block export TF_LOG_PATH=./terraform.log For more on debugging OpenTofu, check out the section on [Debugging](https://opentofu.org/docs/v1.10/internals/debugging/) . TF\_INPUT[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_input "Direct link to TF_INPUT") ------------------------------------------------------------------------------------------------------------------- If set to "false" or "0", causes tofu commands to behave as if the `-input=false` flag was specified. This is used when you want to disable prompts for variables that haven't had their values specified. For example: Code Block export TF_INPUT=0 TF\_VAR\_name[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_var_name "Direct link to TF_VAR_name") ----------------------------------------------------------------------------------------------------------------------------- Environment variables can be used to set variables. The environment variables must be in the format `TF_VAR_name` and this will be checked last for a value. For example: Code Block export TF_VAR_region=us-west-1export TF_VAR_ami=ami-049d8641export TF_VAR_alist='[1,2,3]'export TF_VAR_amap='{ foo = "bar", baz = "qux" }' For more on how to use `TF_VAR_name` in context, check out the section on [Variable Configuration](https://opentofu.org/docs/v1.10/language/values/variables/) . TF\_CLI\_ARGS and TF\_CLI\_ARGS\_name[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_cli_args-and-tf_cli_args_name "Direct link to TF_CLI_ARGS and TF_CLI_ARGS_name") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The value of `TF_CLI_ARGS` will specify additional arguments to the command-line. This allows easier automation in CI environments as well as modifying default behavior of OpenTofu on your own system. These arguments are inserted directly _after_ the subcommand (such as `plan`) and _before_ any flags specified directly on the command-line. This behavior ensures that flags on the command-line take precedence over environment variables. For example, the following command: `TF_CLI_ARGS="-input=false" tofu apply -force` is the equivalent to manually typing: `tofu apply -input=false -force`. The flag `TF_CLI_ARGS` affects all OpenTofu commands. If you specify a named command in the form of `TF_CLI_ARGS_name` then it will only affect that command. As an example, to specify that only plans never refresh, you can set `TF_CLI_ARGS_plan="-refresh=false"`. The value of the flag is parsed as if you typed it directly to the shell. Double and single quotes are allowed to capture strings and arguments will be separated by spaces otherwise. TF\_DATA\_DIR[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_data_dir "Direct link to TF_DATA_DIR") ----------------------------------------------------------------------------------------------------------------------------- `TF_DATA_DIR` changes the location where OpenTofu keeps its per-working-directory data, such as the current backend configuration. By default this data is written into a `.terraform` subdirectory of the current directory, but the path given in `TF_DATA_DIR` will be used instead if non-empty. In most cases it should not be necessary to set this variable, but it may be useful to do so if e.g. the working directory is not writable. The data directory is used to retain data that must persist from one command to the next, so it's important to have this variable set consistently throughout all of the OpenTofu workflow commands (starting with `tofu init`) or else OpenTofu may be unable to find providers, modules, and other artifacts. TF\_WORKSPACE[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_workspace "Direct link to TF_WORKSPACE") ------------------------------------------------------------------------------------------------------------------------------- For multi-environment deployment, in order to select a workspace, instead of doing `tofu workspace select your_workspace`, it is possible to use this environment variable. Using TF\_WORKSPACE allow and override workspace selection. For example: Code Block export TF_WORKSPACE=your_workspace Using this environment variable is recommended only for non-interactive usage, since in a local shell environment it can be easy to forget the variable is set and apply changes to the wrong state. For more information regarding workspaces, check out the section on [Using Workspaces](https://opentofu.org/docs/v1.10/language/state/workspaces/) . TF\_IN\_AUTOMATION[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_in_automation "Direct link to TF_IN_AUTOMATION") -------------------------------------------------------------------------------------------------------------------------------------------- If `TF_IN_AUTOMATION` is set to any non-empty value, OpenTofu adjusts its output to avoid suggesting specific commands to run next. This can make the output more consistent and less confusing in workflows where users don't directly execute OpenTofu commands, like in CI systems or other wrapping applications. This is a purely cosmetic change to OpenTofu's human-readable output, and the exact output differences can change between minor OpenTofu versions. TF\_REGISTRY\_DISCOVERY\_RETRY[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_registry_discovery_retry "Direct link to TF_REGISTRY_DISCOVERY_RETRY") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Set `TF_REGISTRY_DISCOVERY_RETRY` to configure the max number of request retries the remote registry client will attempt for client connection errors or 500-range responses that are safe to retry. TF\_REGISTRY\_CLIENT\_TIMEOUT[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_registry_client_timeout "Direct link to TF_REGISTRY_CLIENT_TIMEOUT") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The default client timeout for requests to the remote registry is 10s. `TF_REGISTRY_CLIENT_TIMEOUT` can be configured and increased during exceptional circumstances. Code Block export TF_REGISTRY_CLIENT_TIMEOUT=15 TF\_CLI\_CONFIG\_FILE[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_cli_config_file "Direct link to TF_CLI_CONFIG_FILE") --------------------------------------------------------------------------------------------------------------------------------------------------- The location of the [OpenTofu CLI configuration file](https://opentofu.org/docs/v1.10/cli/config/config-file/) . Code Block export TF_CLI_CONFIG_FILE="$HOME/.tofurc-custom" TF\_PLUGIN\_CACHE\_DIR[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_plugin_cache_dir "Direct link to TF_PLUGIN_CACHE_DIR") ------------------------------------------------------------------------------------------------------------------------------------------------------ The `TF_PLUGIN_CACHE_DIR` environment variable is an alternative way to set [the `plugin_cache_dir` setting in the CLI configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-plugin-cache) . You can also use `TF_PLUGIN_CACHE_MAY_BREAK_DEPENDENCY_LOCK_FILE` to activate [the transitional compatibility setting `plugin_cache_may_break_dependency_lock_file`](https://opentofu.org/docs/v1.10/cli/config/config-file/#allowing-the-provider-plugin-cache-to-break-the-dependency-lock-file) . TF\_IGNORE[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_ignore "Direct link to TF_IGNORE") ---------------------------------------------------------------------------------------------------------------------- If `TF_IGNORE` is set to "trace", OpenTofu will output debug messages to display ignored files and folders. This is useful when debugging large repositories with `.terraformignore` files. Code Block export TF_IGNORE=trace For more details on `.terraformignore`, please see [Excluding Files from Upload with .terraformignore](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#excluding-files-from-upload-with-terraformignore) . TF\_PROVIDER\_DOWNLOAD\_RETRY[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_provider_download_retry "Direct link to TF_PROVIDER_DOWNLOAD_RETRY") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Set `TF_PROVIDER_DOWNLOAD_RETRY` to configure the max number of request retries the remote provider client will attempt for client connection errors or 500-range responses that are safe to retry. Code Block export TF_PROVIDER_DOWNLOAD_RETRY=3 TF\_STATE\_PERSIST\_INTERVAL[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_state_persist_interval "Direct link to TF_STATE_PERSIST_INTERVAL") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Set `TF_STATE_PERSIST_INTERVAL` to configure the interval (in seconds) between state persistence. Increased interval could be useful when working with huge states (> 100k resources) where upload to a cloud service could take a significant amount of time. Default persistence interval is 20 seconds (it also the lowest possible value for this parameter). The following command sets persistence interval to 5 minutes (300 seconds): Code Block export TF_STATE_PERSIST_INTERVAL=300 Cloud Backend CLI Integration[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#cloud-backend-cli-integration "Direct link to Cloud Backend CLI Integration") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The CLI integration with cloud backends lets you use them on the command line. The integration requires including a `cloud` block in your OpenTofu configuration. You can define its arguments directly in your configuration file or supply them through environment variables, which can be useful for non-interactive workflows like Continuous Integration (CI). Refer to [Cloud Backend Settings](https://opentofu.org/docs/v1.10/cli/cloud/settings/#environment-variables) for a full list of `cloud` block environment variables. TF\_ENCRYPTION[​](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_encryption "Direct link to TF_ENCRYPTION") ---------------------------------------------------------------------------------------------------------------------------------- The `TF_ENCRYPTION` environment variable is an alternate method of specifying the contents of the `terraform { encryption {} }` block. If provided, it will be parsed as either HCL or JSON and override configuration present in the .tf config files. Code Block # Add/Override encryption key_provider.static.mykpexport TF_ENCRYPTION='key_provider "static" "mykp" { key = "6f6f706830656f67686f6834616872756f3751756165686565796f6f72653169" }' Warning If the key (or similar) has non-alphanumeric characters in it, beware that your shell may not interpret them literally. Special characters are shell dependent, but some common examples are dollar signs for variable interpolation or backslashes for character escaping. Make sure your secret doesn't get changed by your shell without you realizing. This is also shell dependent, but common ways of avoiding this are using single quotes or escaping special characters with a backslash. * [TF\_LOG](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_log) * [TF\_LOG\_PATH](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_log_path) * [TF\_INPUT](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_input) * [TF\_VAR\_name](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_var_name) * [TF\_CLI\_ARGS and TF\_CLI\_ARGS\_name](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_cli_args-and-tf_cli_args_name) * [TF\_DATA\_DIR](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_data_dir) * [TF\_WORKSPACE](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_workspace) * [TF\_IN\_AUTOMATION](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_in_automation) * [TF\_REGISTRY\_DISCOVERY\_RETRY](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_registry_discovery_retry) * [TF\_REGISTRY\_CLIENT\_TIMEOUT](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_registry_client_timeout) * [TF\_CLI\_CONFIG\_FILE](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_cli_config_file) * [TF\_PLUGIN\_CACHE\_DIR](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_plugin_cache_dir) * [TF\_IGNORE](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_ignore) * [TF\_PROVIDER\_DOWNLOAD\_RETRY](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_provider_download_retry) * [TF\_STATE\_PERSIST\_INTERVAL](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_state_persist_interval) * [Cloud Backend CLI Integration](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#cloud-backend-cli-integration) * [TF\_ENCRYPTION](https://opentofu.org/docs/v1.10/cli/config/environment-variables/#tf_encryption) --- # Command: import | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/import/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: import =============== The `tofu import` command [imports existing resources](https://opentofu.org/docs/v1.10/cli/import/) into OpenTofu. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/import/#usage "Direct link to Usage") -------------------------------------------------------------------------------------------- Usage: `tofu import [options] ADDRESS ID` Import will find the existing resource from ID and import it into your OpenTofu state at the given ADDRESS. ADDRESS must be a valid [resource address](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/) . Because any resource address is valid, the import command can import resources into modules as well as directly into the root of your state. ID is dependent on the resource type being imported. For example, for AWS EC2 instances it is the instance ID (`i-abcd1234`) but for AWS Route53 zones it is the zone ID (`Z12ABC4UGMOZ2N`). Please reference the provider documentation for details on the ID format. If you're unsure, feel free to just try an ID. If the ID is invalid, you'll just receive an error message. Warning OpenTofu expects that each remote object it is managing will be bound to only one resource address, which is normally guaranteed by OpenTofu itself having created all objects. If you import existing objects into OpenTofu, be careful to import each remote object to only one OpenTofu resource address. If you import the same object multiple times, OpenTofu may exhibit unwanted behavior. For more information on this assumption, see [the State section](https://opentofu.org/docs/v1.10/language/state/) . Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu import`. The command-line flags are all optional. The following flags are available: * `-config=path` - Path to directory of OpenTofu configuration files that configure the provider for import. This defaults to your working directory. If this directory contains no OpenTofu configuration files, the provider must be configured via manual input or environmental variables. * `-input=true` - Whether to ask for input for provider configuration. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=0s` - Duration to retry a state lock. * `-no-color` - If specified, output won't contain any color. * `-parallelism=n` - Limit the number of concurrent operation as OpenTofu [walks the graph](https://opentofu.org/docs/v1.10/internals/graph/#walking-the-graph) . Defaults to 10. * `-provider=provider` - **Deprecated** Override the provider configuration to use when importing the object. By default, OpenTofu uses the provider specified in the configuration for the target resource, and that is the best behavior in most cases. * `-var 'foo=bar'` - Set a variable in the OpenTofu configuration. This flag can be set multiple times. Variable values are interpreted as [literal expressions](https://opentofu.org/docs/v1.10/language/expressions/types/) in the OpenTofu language, so list and map values can be specified via this flag. * `-var-file=foo` - Set variables in the OpenTofu configuration from a [variable file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . If a `terraform.tfvars` or any `.auto.tfvars` files are present in the current directory, they will be automatically loaded. `terraform.tfvars` is loaded first and the `.auto.tfvars` files after in alphabetical order. Any files specified by `-var-file` override any values set automatically from files in the working directory. This flag can be used multiple times. This is only useful with the `-config` flag. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.10/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.10/language/settings/backends/remote/) only, `tofu import` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/v1.10/cli/cloud/command-line-arguments/#ignore-remote-version) . For configurations using [the `local` backend](https://opentofu.org/docs/v1.10/language/settings/backends/local/) only, `tofu import` also accepts the legacy options [`-state`, `-state-out`, and `-backup`](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) . Provider Configuration[​](https://opentofu.org/docs/v1.10/cli/commands/import/#provider-configuration "Direct link to Provider Configuration") ----------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu will attempt to load configuration files that configure the provider being used for import. If no configuration files are present or no configuration for that specific provider is present, OpenTofu will prompt you for access credentials. You may also specify environmental variables to configure the provider. The only limitation OpenTofu has when reading the configuration files is that the import provider configurations must not depend on non-variable inputs. For example, a provider configuration cannot depend on a data source. As a working example, if you're importing AWS resources and you have a configuration file with the contents below, then OpenTofu will configure the AWS provider with this file. Code Block variable "access_key" {}variable "secret_key" {}provider "aws" { access_key = "${var.access_key}" secret_key = "${var.secret_key}"} Example: Import into Resource[​](https://opentofu.org/docs/v1.10/cli/commands/import/#example-import-into-resource "Direct link to Example: Import into Resource") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- This example will import an AWS instance into the `aws_instance` resource named `foo`: Code Block $ tofu import aws_instance.foo i-abcd1234 Example: Import into Module[​](https://opentofu.org/docs/v1.10/cli/commands/import/#example-import-into-module "Direct link to Example: Import into Module") ------------------------------------------------------------------------------------------------------------------------------------------------------------- The example below will import an AWS instance into the `aws_instance` resource named `bar` into a module named `foo`: Code Block $ tofu import module.foo.aws_instance.bar i-abcd1234 Example: Import into Resource configured with count[​](https://opentofu.org/docs/v1.10/cli/commands/import/#example-import-into-resource-configured-with-count "Direct link to Example: Import into Resource configured with count") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The example below will import an AWS instance into the first instance of the `aws_instance` resource named `baz` configured with [`count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) : Code Block $ tofu import 'aws_instance.baz[0]' i-abcd1234 Example: Import into Resource configured with for\_each[​](https://opentofu.org/docs/v1.10/cli/commands/import/#example-import-into-resource-configured-with-for_each "Direct link to Example: Import into Resource configured with for_each") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The example below will import an AWS instance into the `"example"` instance of the `aws_instance` resource named `baz` configured with [`for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) : Linux, Mac OS, and UNIX: Code Block $ tofu import 'aws_instance.baz["example"]' i-abcd1234 PowerShell: Code Block $ tofu import 'aws_instance.baz[\"example\"]' i-abcd1234 Windows `cmd.exe`: Code Block $ tofu import aws_instance.baz[\"example\"] i-abcd1234 * [Usage](https://opentofu.org/docs/v1.10/cli/commands/import/#usage) * [Provider Configuration](https://opentofu.org/docs/v1.10/cli/commands/import/#provider-configuration) * [Example: Import into Resource](https://opentofu.org/docs/v1.10/cli/commands/import/#example-import-into-resource) * [Example: Import into Module](https://opentofu.org/docs/v1.10/cli/commands/import/#example-import-into-module) * [Example: Import into Resource configured with count](https://opentofu.org/docs/v1.10/cli/commands/import/#example-import-into-resource-configured-with-count) * [Example: Import into Resource configured with for\_each](https://opentofu.org/docs/v1.10/cli/commands/import/#example-import-into-resource-configured-with-for_each) --- # Command: refresh | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/refresh/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: refresh ================ The `tofu refresh` command reads the current settings from all managed remote objects and updates the OpenTofu state to match. Warning This command is deprecated, because its default behavior is unsafe if you have misconfigured credentials for any of your providers. See below for more information and recommended alternatives. This won't modify your real remote objects, but it will modify the [OpenTofu state](https://opentofu.org/docs/v1.10/language/state/) . You shouldn't typically need to use this command, because OpenTofu automatically performs the same refreshing actions as a part of creating a plan in both the [`tofu plan`](https://opentofu.org/docs/v1.10/cli/commands/plan/) and [`tofu apply`](https://opentofu.org/docs/v1.10/cli/commands/apply/) commands. This command is here primarily for backward compatibility, but we don't recommend using it because it provides no opportunity to review the effects of the operation before updating the state. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/refresh/#usage "Direct link to Usage") --------------------------------------------------------------------------------------------- Usage: `tofu refresh [options]` This command is effectively an alias for the following command: Code Block tofu apply -refresh-only -auto-approve Consequently, it supports all of the same options as [`tofu apply`](https://opentofu.org/docs/v1.10/cli/commands/apply/) except that it does not accept a saved plan file, it doesn't allow selecting a planning mode other than "refresh only", and `-auto-approve` is always enabled. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu refresh`. Automatically applying the effect of a refresh is risky. If you have misconfigured credentials for one or more providers, OpenTofu may be misled into thinking that all of the managed objects have been deleted, causing it to remove all of the tracked objects without any confirmation prompt. Instead, we recommend using the following command in order to get the same effect but with the opportunity to review the changes that OpenTofu has detected before committing them to the state: Code Block tofu apply -refresh-only This alternative command will present an interactive prompt for you to confirm the detected changes. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/refresh/#usage) --- # Command: show | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/show/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: show ============= The `tofu show` command can inspect various OpenTofu artifacts and produce either human-readable or machine-readable descriptions. For example, you can use `tofu show` to inspect a saved plan file to check that the planned operations are acceptable, or to inspect the latest state snapshot. Note When using the `-json` command-line flag, any sensitive values in OpenTofu state will be returned in plain text. For more information, see [Sensitive Data in State](https://opentofu.org/docs/v1.10/language/state/sensitive-data/) . Usage[​](https://opentofu.org/docs/v1.10/cli/commands/show/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------ Usage: `tofu show [target-selection-option] [other-options]` Use one of the following target selection options to specify the artifact to inspect: * `-state`: Inspect the latest state snapshot, if any. * `-plan=FILENAME`: Inspect the plan stored in the given saved plan file. The `-state` option is the default if none of these options are used. The target-selection options are mutually-exclusive. This command also accepts the following additional options: * `-no-color`: Disables the use of terminal escape sequences in human-oriented output. * `-json`: Selects the machine-readable JSON output format, instead of the default human-oriented output. * `-var` and `-var-file`: Specifies values for any input variables used in module source addresses or backend settings in the current configuration. * `-show-sensitive`: If specified, sensitive values will be displayed. This command relies on schema information from provider plugins to fully understand the provider-specific data structures in state, plan, and configuration artifacts. If you are currently using different provider versions than were used when creating the selected artifact then you may need to use `tofu apply` (or similar) to allow OpenTofu to upgrade the stored data to match the latest provider schemas. JSON Output[​](https://opentofu.org/docs/v1.10/cli/commands/show/#json-output "Direct link to JSON Output") ------------------------------------------------------------------------------------------------------------ When using the `-json` option, the structure of the machine-readable output depends on the selected artifact type: * `-state` returns [the JSON state representation](https://opentofu.org/docs/v1.10/internals/json-format/#state-representation) . * `-plan=FILENAME` returns the [the JSON plan representation](https://opentofu.org/docs/v1.10/internals/json-format/#plan-representation) , which also includes information about the configuration and prior state that the plan was based on. Legacy Usage[​](https://opentofu.org/docs/v1.10/cli/commands/show/#legacy-usage "Direct link to Legacy Usage") --------------------------------------------------------------------------------------------------------------- For backward compatibility with older versions of OpenTofu, this command also supports a different usage pattern: `tofu show [other-options] ` In this style, none of the explicit target selection options can be used and instead OpenTofu inspects the given file and reacts in the following ways: * If the file can be loaded as a saved plan file, behaves like `-plan=FILENAME` with the same file. * If the file can be parsed as a local state snapshot file such as those created by `tofu state pull`, inspects the content of that state file using the same output format as would normally be used to inspect the latest state snapshot. The selected state snapshot file must be one associated with the configuration in the current working directory, or else the results are unspecified because the available providers might not match those that were used to create the data in the state snapshot. Unless you need the legacy behavior of inspecting an arbitrary state snapshot file, we recommend using the new explicit target selection options to make it clearer to OpenTofu what artifact type you wish to inspect. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/show/#usage) * [JSON Output](https://opentofu.org/docs/v1.10/cli/commands/show/#json-output) * [Legacy Usage](https://opentofu.org/docs/v1.10/cli/commands/show/#legacy-usage) --- # Import Usage | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/import/usage/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Import Usage ============ Use the `tofu import` command to import existing infrastructure to OpenTofu state. The `tofu import` command can only import one resource at a time. It cannot simultaneously import an entire collection of resources, like an AWS VPC. Warning OpenTofu expects that each remote object it is managing will be bound to only one resource address, which is normally guaranteed by OpenTofu itself having created all objects. If you import existing objects into OpenTofu, be careful to import each remote object to only one OpenTofu resource address. If you import the same object multiple times, OpenTofu may exhibit unwanted behavior. For more information on this assumption, see [the State section](https://opentofu.org/docs/v1.10/cli/state/) . To import a resource, first write a resource block for it in your configuration, establishing the name by which it will be known to OpenTofu: Code Block resource "aws_instance" "example" { # ...instance configuration...} The name "example" here is local to the module where it is declared and is chosen by the configuration author. This is distinct from any ID issued by the remote system, which may change over time while the resource name remains constant. If desired, you can leave the body of the resource block blank for now and return to fill it in once the instance is imported. Now `tofu import` can be run to attach an existing instance to this resource configuration: Code Block $ tofu import aws_instance.example i-abcd1234 This command locates the AWS EC2 instance with ID `i-abcd1234`. Then it attaches the existing settings of the instance, as described by the EC2 API, to the name `aws_instance.example` of a module. In this example the module path implies that the root module is used. Finally, the mapping is saved in the OpenTofu state. It is also possible to import to resources in child modules, using their paths, and to single instances of a resource with `count` or `for_each` set. See [_Resource Addressing_](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/) for more details on how to specify a target resource. The syntax of the given ID is dependent on the resource type being imported. For example, AWS instances use an opaque ID issued by the EC2 API, but AWS Route53 Zones use the domain name itself. Consult the documentation for each importable resource for details on what form of ID is required. As a result of the above command, the resource is recorded in the state file. You can now run `tofu plan` to see how the configuration compares to the imported resource, and make any adjustments to the configuration to align with the current (or desired) state of the imported object. Complex Imports[​](https://opentofu.org/docs/v1.10/cli/import/usage/#complex-imports "Direct link to Complex Imports") ----------------------------------------------------------------------------------------------------------------------- The above import is considered a "simple import": one resource is imported into the state file. An import may also result in a "complex import" where multiple resources are imported. For example, an AWS network ACL imports an `aws_network_acl` but also one `aws_network_acl_rule` for each rule. In this scenario, the secondary resources will not already exist in configuration, so it is necessary to consult the import output and create a `resource` block in configuration for each secondary resource. If this is not done, OpenTofu will plan to destroy the imported objects on the next run. If you want to rename or otherwise move the imported resources, the [state management commands](https://opentofu.org/docs/v1.10/cli/commands/state/) can be used. * [Complex Imports](https://opentofu.org/docs/v1.10/cli/import/usage/#complex-imports) --- # Private Registries | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/private_registry/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Private Registries ================== OpenTofu, by default, uses the public registry at [registry.opentofu.org](https://registry.opentofu.org/) . However, organizations may have a need for a private registry for modules or providers that need to be kept private. There are several project that implement the [terraform registry API](https://developer.hashicorp.com/terraform/registry/api-docs) , aimed at providing this functionality of hosting a private registry. They are also compatible with OpenTofu. Some of the projects only support providers, some only support modules, and some support both. Choose one that is appropriate for your use case. List of Private Registries[​](https://opentofu.org/docs/v1.10/cli/private_registry/#list-of-private-registries "Direct link to List of Private Registries") ------------------------------------------------------------------------------------------------------------------------------------------------------------ The list of projects is available at [awesome-opentofu](https://github.com/virtualroot/awesome-opentofu?tab=readme-ov-file#registry) . How to Use[​](https://opentofu.org/docs/v1.10/cli/private_registry/#how-to-use "Direct link to How to Use") ------------------------------------------------------------------------------------------------------------ Follow the documentation provided by each registry to integrate it with your OpenTofu projects. * [List of Private Registries](https://opentofu.org/docs/v1.10/cli/private_registry/#list-of-private-registries) * [How to Use](https://opentofu.org/docs/v1.10/cli/private_registry/#how-to-use) --- # Plugin Signing | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/plugins/signing/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Plugin Signing ============== Note OpenTofu only authenticates provider plugins fetched from a registry. OpenTofu providers installed from the Registry are cryptographically signed and the signature is verified at time of installation. OpenTofu does **NOT** support fetching and using unsigned binaries, but you can manually install unsigned binaries. You should take extreme care when doing so as no programmatic authentication is performed. Environment Variables[​](https://opentofu.org/docs/v1.10/cli/plugins/signing/#environment-variables "Direct link to Environment Variables") -------------------------------------------------------------------------------------------------------------------------------------------- ### `OPENTOFU_ENFORCE_GPG_VALIDATION=false`[​](https://opentofu.org/docs/v1.10/cli/plugins/signing/#opentofu_enforce_gpg_validationfalse "Direct link to opentofu_enforce_gpg_validationfalse") A temporary change has been introduced to skip GPG validation under specific conditions: * **Registry Scope**: This change only affects provider packages from the default registry. * **Key Availability**: GPG validation will be skipped when and only when the provider's GPG keys are not available in the default registry. * **Temporary Measure**: This is a stopgap measure until GPG keys for all providers can be populated in the default registry. While this offers operational flexibility, it does reduce the level of security assurance for affected packages. Users who prioritize security should set the `OPENTOFU_ENFORCE_GPG_VALIDATION` environment variable to `true` to enforce GPG validation of all providers. **Future Removal**: We intend to remove this feature once all GPG keys are populated in the default registry, reverting to a strict GPG validation process for all providers. ### `OPENTOFU_ENFORCE_GPG_EXPIRATION=false`[​](https://opentofu.org/docs/v1.10/cli/plugins/signing/#opentofu_enforce_gpg_expirationfalse "Direct link to opentofu_enforce_gpg_expirationfalse") Many older keys present in the registry have expired and are no longer strictly valid. Historically, Terraform has not cared about the expiration date of keys in the registry and has ignored that field. When switching to a new crypto library, this functionality was made available. For legacy reasons, this is currently disabled by default (set to `false`), but may default to `true` in a future release as workflows are built into the registry for keeping keys up to date. * [Environment Variables](https://opentofu.org/docs/v1.10/cli/plugins/signing/#environment-variables) * [`OPENTOFU_ENFORCE_GPG_VALIDATION=false`](https://opentofu.org/docs/v1.10/cli/plugins/signing/#opentofu_enforce_gpg_validationfalse) * [`OPENTOFU_ENFORCE_GPG_EXPIRATION=false`](https://opentofu.org/docs/v1.10/cli/plugins/signing/#opentofu_enforce_gpg_expirationfalse) --- # OCI Registry Integrations | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/oci_registries/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page OCI Registry Integrations ========================= Some of OpenTofu's features can be configured to interact with OCI Registries. These integrations are designed to support registries that implement [OCI Distribution v1.1.0](https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md) . Registries that implement earlier versions may work, depending on how strictly they validate submitted manifests, but we cannot officially support them because v1.1.0 is the first protocol version that includes explicit support for non-container-image artifacts. OCI Registry Credentials[​](https://opentofu.org/docs/v1.10/cli/oci_registries/#oci-registry-credentials "Direct link to OCI Registry Credentials") ---------------------------------------------------------------------------------------------------------------------------------------------------- By default, OpenTofu searches for OCI Registry credentials in the same locations as other tools in the OCI ecosystem, such as Docker CLI, Podman, Buildah, ORAS, etc. If you have already logged in to the registry you intend to use with the login facility from one of these programs then OpenTofu should discover and use the configured credentials automatically. If you need more control over the behavior, refer to [OCI Registry Credentials](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/) . OpenTofu Modules in OCI Registries[​](https://opentofu.org/docs/v1.10/cli/oci_registries/#opentofu-modules-in-oci-registries "Direct link to OpenTofu Modules in OCI Registries") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu supports OCI Registries as one of its many supported [module source address types](https://opentofu.org/docs/v1.10/language/modules/sources/) . No special configuration is required to enable this source address type aside from ensuring that you have configured whatever credentials are needed to communicate with the specified remote repository. For more information on how to create suitable artifacts for use as OpenTofu module packages, refer to [Module Packages in OCI Registries](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/) . OpenTofu Providers in OCI Registries[​](https://opentofu.org/docs/v1.10/cli/oci_registries/#opentofu-providers-in-oci-registries "Direct link to OpenTofu Providers in OCI Registries") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu supports OCI Registries as a secondary installation source for provider plugin packages. You can configure OpenTofu to retrieve some or all providers from an OCI Registry instead of from each provider's primary OpenTofu Provider Registry. For more information, refer to [Provider Mirrors in OCI Registries](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/) . OpenTofu does not yet support using an OCI Registry as the _primary_ installation source for a provider, but we are hoping to allow that in a future version. * [OCI Registry Credentials](https://opentofu.org/docs/v1.10/cli/oci_registries/#oci-registry-credentials) * [OpenTofu Modules in OCI Registries](https://opentofu.org/docs/v1.10/cli/oci_registries/#opentofu-modules-in-oci-registries) * [OpenTofu Providers in OCI Registries](https://opentofu.org/docs/v1.10/cli/oci_registries/#opentofu-providers-in-oci-registries) --- # Command: state list | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/state/list/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state list =================== The `tofu state list` command is used to list resources within a [OpenTofu state](https://opentofu.org/docs/v1.10/language/state/) . Usage[​](https://opentofu.org/docs/v1.10/cli/commands/state/list/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------ Usage: `tofu state list [options] [address...]` The command will list all resources in the state file matching the given addresses (if any). If no addresses are given, all resources are listed. The resources listed are sorted according to module depth order followed by alphabetical. This means that resources that are in your immediate configuration are listed first, and resources that are more deeply nested within modules are listed last. For complex infrastructures, the state can contain thousands of resources. To filter these, provide one or more patterns to the command. Patterns are in [resource addressing format](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/) . Note Use of variables in [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu state list`. The command-line flags are all optional. The following flags are available: * `-state=path` - Path to the state file. Defaults to "terraform.tfstate". Ignored when [remote state](https://opentofu.org/docs/v1.10/language/state/remote/) is used. * `-id=id` - ID of resources to show. Ignored when unset. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. Example: All Resources[​](https://opentofu.org/docs/v1.10/cli/commands/state/list/#example-all-resources "Direct link to Example: All Resources") -------------------------------------------------------------------------------------------------------------------------------------------------- This example will list all resources, including modules: Code Block $ tofu state listaws_instance.fooaws_instance.bar[0]aws_instance.bar[1]module.elb.aws_elb.main Example: Filtering by Resource[​](https://opentofu.org/docs/v1.10/cli/commands/state/list/#example-filtering-by-resource "Direct link to Example: Filtering by Resource") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This example will only list resources for the given name: Code Block $ tofu state list aws_instance.baraws_instance.bar[0]aws_instance.bar[1] Example: Filtering by Module[​](https://opentofu.org/docs/v1.10/cli/commands/state/list/#example-filtering-by-module "Direct link to Example: Filtering by Module") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- This example will list resources in the given module and any submodules: Code Block $ tofu state list module.elbmodule.elb.aws_elb.mainmodule.elb.module.secgroups.aws_security_group.sg Example: Filtering by ID[​](https://opentofu.org/docs/v1.10/cli/commands/state/list/#example-filtering-by-id "Direct link to Example: Filtering by ID") -------------------------------------------------------------------------------------------------------------------------------------------------------- This example will only list the resource whose ID is specified on the command line. This is useful to find where in your configuration a specific resource is located. Code Block $ tofu state list -id=sg-1234abcdmodule.elb.aws_security_group.sg * [Usage](https://opentofu.org/docs/v1.10/cli/commands/state/list/#usage) * [Example: All Resources](https://opentofu.org/docs/v1.10/cli/commands/state/list/#example-all-resources) * [Example: Filtering by Resource](https://opentofu.org/docs/v1.10/cli/commands/state/list/#example-filtering-by-resource) * [Example: Filtering by Module](https://opentofu.org/docs/v1.10/cli/commands/state/list/#example-filtering-by-module) * [Example: Filtering by ID](https://opentofu.org/docs/v1.10/cli/commands/state/list/#example-filtering-by-id) --- # Provisioning Infrastructure with OpenTofu | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/run/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provisioning Infrastructure with OpenTofu ========================================= OpenTofu's primary function is to create, modify, and destroy infrastructure resources to match the desired state described in a [OpenTofu configuration](https://opentofu.org/docs/v1.10/language/) . When people refer to "running OpenTofu," they generally mean performing these provisioning actions in order to affect real infrastructure objects. The OpenTofu binary has many other subcommands for a wide variety of administrative actions, but these basic provisioning tasks are the core of OpenTofu. OpenTofu's provisioning workflow relies on three commands: `plan`, `apply`, and `destroy`. All of these commands require an [initialized](https://opentofu.org/docs/v1.10/cli/init/) working directory, and all of them act only upon the currently selected [workspace](https://opentofu.org/docs/v1.10/cli/workspaces/) . Planning[​](https://opentofu.org/docs/v1.10/cli/run/#planning "Direct link to Planning") ----------------------------------------------------------------------------------------- The `tofu plan` command evaluates a OpenTofu configuration to determine the desired state of all the resources it declares, then compares that desired state to the real infrastructure objects being managed with the current working directory and workspace. It uses state data to determine which real objects correspond to which declared resources, and checks the current state of each resource using the relevant infrastructure provider's API. Once it has determined the difference between the current state and the desired state, `tofu plan` presents a description of the changes necessary to achieve the desired state. It _does not_ perform any actual changes to real world infrastructure objects; it only presents a plan for making changes. Plans are usually run to validate configuration changes and confirm that the resulting actions are as expected. However, `tofu plan` can also save its plan as a runnable artifact, which `tofu apply` can use to carry out those exact changes. For details, see [the `tofu plan` command](https://opentofu.org/docs/v1.10/cli/commands/plan/) . Applying[​](https://opentofu.org/docs/v1.10/cli/run/#applying "Direct link to Applying") ----------------------------------------------------------------------------------------- The `tofu apply` command performs a plan just like `tofu plan` does, but then actually carries out the planned changes to each resource using the relevant infrastructure provider's API. It asks for confirmation from the user before making any changes, unless it was explicitly told to skip approval. By default, `tofu apply` performs a fresh plan right before applying changes, and displays the plan to the user when asking for confirmation. However, it can also accept a plan file produced by `tofu plan` in lieu of running a new plan. You can use this to reliably perform an exact set of pre-approved changes, even if the configuration or the state of the real infrastructure has changed in the minutes since the original plan was created. For details, see [the `tofu apply` command](https://opentofu.org/docs/v1.10/cli/commands/apply/) . Destroying[​](https://opentofu.org/docs/v1.10/cli/run/#destroying "Direct link to Destroying") ----------------------------------------------------------------------------------------------- The `tofu destroy` command destroys all of the resources being managed by the current working directory and workspace, using state data to determine which real world objects correspond to managed resources. Like `tofu apply`, it asks for confirmation before proceeding. A destroy behaves exactly like deleting every resource from the configuration and then running an apply, except that it doesn't require editing the configuration. This is more convenient if you intend to provision similar resources at a later date. For details, see [the `tofu destroy` command](https://opentofu.org/docs/v1.10/cli/commands/destroy/) . * [Planning](https://opentofu.org/docs/v1.10/cli/run/#planning) * [Applying](https://opentofu.org/docs/v1.10/cli/run/#applying) * [Destroying](https://opentofu.org/docs/v1.10/cli/run/#destroying) --- # Command: plan | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/plan/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: plan ============= The `tofu plan` command creates an execution plan, which lets you preview the changes that OpenTofu plans to make to your infrastructure. By default, when OpenTofu creates a plan it: * Reads the current state of any already-existing remote objects to make sure that the OpenTofu state is up-to-date. * Compares the current configuration to the prior state and noting any differences. * Proposes a set of change actions that should, if applied, make the remote objects match the configuration. The `plan` command alone does not actually carry out the proposed changes You can use this command to check whether the proposed changes match what you expected before you apply the changes or share your changes with your team for broader review. If OpenTofu detects that no changes are needed to resource instances or to root module output values, `tofu plan` will report that no actions need to be taken. If you are using OpenTofu directly in an interactive terminal and you expect to apply the changes OpenTofu proposes, you can alternatively run [`tofu apply`](https://opentofu.org/docs/v1.10/cli/commands/apply/) directly. By default, the "apply" command automatically generates a new plan and prompts for you to approve it. You can use the optional `-out=FILE` option to save the generated plan to a file on disk, which you can later execute by passing the file to [`tofu apply`](https://opentofu.org/docs/v1.10/cli/commands/apply/) as an extra argument. This two-step workflow is primarily intended for when running OpenTofu in automation. If you run `tofu plan` without the `-out=FILE` option then it will create a _speculative plan_, which is a description of the effect of the plan but without any intent to actually apply it. In teams that use a version control and code review workflow for making changes to real infrastructure, developers can use speculative plans to verify the effect of their changes before submitting them for code review. However, it's important to consider that other changes made to the target system in the meantime might cause the final effect of a configuration change to be different than what an earlier speculative plan indicated, so you should always re-check the final non-speculative plan before applying to make sure that it still matches your intent. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/plan/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------ Usage: `tofu plan [options]` The `plan` subcommand looks in the current working directory for the root module configuration. Because the plan command is one of the main commands of OpenTofu, it has a variety of different options, described in the following sections. However, most of the time you should not need to set any of these options, because a OpenTofu configuration should typically be designed to work with no special additional options for routine work. The remaining sections on this page describe the various options: * **[Planning Modes](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-modes) **: There are some special alternative planning modes that you can use for some special situations where your goal is not just to change the remote system to match your configuration. * **[Planning Options](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-options) **: Alongside the special planning modes, there are also some options you can set in order to customize the planning process for unusual needs. * **[Resource Targeting](https://opentofu.org/docs/v1.10/cli/commands/plan/#resource-targeting) ** is one particular special planning option that has some important caveats associated with it. * **[Other Options](https://opentofu.org/docs/v1.10/cli/commands/plan/#other-options) **: These change the behavior of the planning command itself, rather than customizing the content of the generated plan. Planning Modes[​](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-modes "Direct link to Planning Modes") --------------------------------------------------------------------------------------------------------------------- The previous section describes OpenTofu's default planning behavior, which changes the remote system to match the changes you make to your configuration. OpenTofu has two alternative planning modes, each of which creates a plan with a different intended outcome. These options are available for both `tofu plan` and [`tofu apply`](https://opentofu.org/docs/v1.10/cli/commands/apply/) . * **Destroy mode:** creates a plan whose goal is to destroy all remote objects that currently exist, leaving an empty OpenTofu state. It is the same as running [`tofu destroy`](https://opentofu.org/docs/v1.10/cli/commands/destroy/) . Destroy mode can be useful for situations like transient development environments, where the managed objects cease to be useful once the development task is complete. Activate destroy mode using the `-destroy` command line option. * **Refresh-only mode:** creates a plan whose goal is only to update the OpenTofu state and any root module output values to match changes made to remote objects outside of OpenTofu. This can be useful if you've intentionally changed one or more remote objects outside of the usual workflow (e.g. while responding to an incident) and you now need to reconcile OpenTofu's records with those changes. Activate refresh-only mode using the `-refresh-only` command line option. In situations where we need to discuss the default planning mode that OpenTofu uses when none of the alternative modes are selected, we refer to it as "Normal mode". Because these alternative modes are for specialized situations only, some other OpenTofu documentation only discusses the normal planning mode. The planning modes are all mutually-exclusive, so activating any non-default planning mode disables the "normal" planning mode, and you can't use more than one alternative mode at the same time. Planning Options[​](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-options "Direct link to Planning Options") --------------------------------------------------------------------------------------------------------------------------- In addition to alternate [planning modes](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-modes) , there are several options that can modify planning behavior. These options are available for both `tofu plan` and [`tofu apply`](https://opentofu.org/docs/v1.10/cli/commands/apply/) . * `-refresh=false` - Disables the default behavior of synchronizing the OpenTofu state with remote objects before checking for configuration changes. This can make the planning operation faster by reducing the number of remote API requests. However, setting `refresh=false` causes OpenTofu to ignore external changes, which could result in an incomplete or incorrect plan. You cannot use `refresh=false` in refresh-only planning mode because it would effectively disable the entirety of the planning operation. * `-replace=ADDRESS` - Instructs OpenTofu to plan to replace the resource instance with the given address. This is helpful when one or more remote objects have become degraded, and you can use replacement objects with the same configuration to align with immutable infrastructure patterns. OpenTofu will use a "replace" action if the specified resource would normally cause an "update" action or no action at all. Include this option multiple times to replace several objects at once. You cannot use `-replace` with the `-destroy` option. * `-exclude=ADDRESS` - Instructs OpenTofu to focus its planning efforts only on resource instances which do not match the given excluded address, and that do not depend on any such resources or modules that were excluded. Note Use `-exclude=ADDRESS` in exceptional circumstances only, such as recovering from mistakes or working around OpenTofu limitations. Refer to [Resource Targeting](https://opentofu.org/docs/v1.10/cli/commands/plan/#resource-targeting) for more details. * `-exclude-file=FILENAME` - Similar to `-exclude` but with multiple addresses specified in a separate file rather than directly on the command line. * `-target=ADDRESS` - Instructs OpenTofu to focus its planning efforts only on resource instances which match the given address and on any objects that those instances depend on. Note Use `-target=ADDRESS` in exceptional circumstances only, such as recovering from mistakes or working around OpenTofu limitations. Refer to [Resource Targeting](https://opentofu.org/docs/v1.10/cli/commands/plan/#resource-targeting) for more details. * `-target-file=FILENAME` - Similar to `-target` but with multiple addresses specified in a separate file rather than directly on the command line. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. ### Input Variables on the Command Line[​](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line "Direct link to Input Variables on the Command Line") You can use the `-var` command line option to specify values for [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in your root module. However, to do so will require writing a command line that is parsable both by your chosen command line shell _and_ OpenTofu, which can be complicated for expressions involving lots of quotes and escape sequences. In most cases we recommend using the `-var-file` option instead, and write your actual values in a separate file so that OpenTofu can parse them directly, rather than interpreting the result of your shell's parsing. Warning OpenTofu will error if you include a space before or after the equals sign (e.g., `-var "length = 2"`). To use `-var` on a Unix-style shell on a system like Linux or macOS we recommend writing the option argument in single quotes `'` to ensure the shell will interpret the value literally: Code Block tofu plan -var 'name=value' If your intended value also includes a single quote then you'll still need to escape that for correct interpretation by your shell, which also requires temporarily ending the quoted sequence so that the backslash escape character will be significant: Code Block tofu plan -var 'name=va'\''lue' When using OpenTofu on Windows, we recommend using the Windows Command Prompt (`cmd.exe`). When you pass a variable value to OpenTofu from the Windows Command Prompt, use double quotes `"` around the argument: Code Block tofu plan -var "name=value" If your intended value includes literal double quotes then you'll need to escape those with a backslash: Code Block tofu plan -var "name=va\"lue" PowerShell on Windows cannot correctly pass literal quotes to external programs, so we do not recommend using OpenTofu with PowerShell when you are on Windows. Use Windows Command Prompt instead. The appropriate syntax for writing the variable value is different depending on the variable's [type constraint](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/) . The primitive types `string`, `number`, and `bool` all expect a direct string value with no special punctuation except that required by your shell, as shown in the above examples. For all other type constraints, including list, map, and set types and the special `any` keyword, you must write a valid OpenTofu language expression representing the value, and write any necessary quoting or escape characters to ensure it will pass through your shell literally to OpenTofu. For example, for a `list(string)` type constraint: Code Block # Unix-style shelltofu plan -var 'name=["a", "b", "c"]'# Windows Command Prompt (do not use PowerShell on Windows)tofu plan -var "name=[\"a\", \"b\", \"c\"]" Similar constraints apply when setting input variables using environment variables. For more information on the various methods for setting root module input variables, see [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) . ### Resource Targeting[​](https://opentofu.org/docs/v1.10/cli/commands/plan/#resource-targeting "Direct link to Resource Targeting") You can use the `-target`, `-target-file`, `-exclude`, and `-exclude-file` options to activate resource targeting, which focuses OpenTofu's attention on only a subset of the resource instances that are declared in the configuration or tracked in the current state. Using `-target` or `-target-file` focuses OpenTofu's attention only on resource instances that match the given target addresses and resource instances that are dependencies of those. Using `-exclude` or `-exclude-file` instead focuses OpenTofu's attention on resource instances _other than_ those that match and anything that depends on those. Positive targeting using `-target` and `-target-file` is mutually exclusive with negative targeting using `-exclude` and `-exclude-file`. You cannot use both the target options and the exclude options together in a single command. Specify the resource instances to target using [resource address syntax](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/) . For `-target` and `-exclude`, refer to [Resource Addresses on the Command Line](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#resource-addresses-on-the-command-line) . For `-target-file` and `-exclude-file`, refer to [Resource Addresses in Targeting Files](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#resource-addresses-in-targeting-files) . OpenTofu matches resource instances with the given resource addresses as follows: * If the given address identifies one specific resource instance, OpenTofu will select that instance alone. For resources with either `count` or `for_each` set, a resource instance address must include the instance index part, like `aws_instance.example[0]`. Your shell may assign special meaning to some punctuation characters used in a resource instance address, such as quotes and brackets, so it's important to properly quote or escape resource instance addresses written directly on the command line in `-target` or `-exclude` options as described in [Resource Addresses on the Command Line](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#resource-addresses-on-the-command-line) . * If the given address identifies a resource as a whole, OpenTofu will select all of the instances of that resource. For resources with either `count` or `for_each` set, this means selecting _all_ instance indexes currently associated with that resource. For single-instance resources (without either `count` or `for_each`), the resource address and the resource instance address are identical, so this possibility does not apply. * If the given address identifies an entire module instance, OpenTofu will select all instances of all resources that belong to that module instance and all of its child module instances. This targeting capability is provided for exceptional circumstances, such as recovering from mistakes or working around OpenTofu limitations. It is _not recommended_ to use these options for routine operations, because that can lead to undetected configuration drift and confusion about how the true state of resources relates to configuration. Instead of using resource targeting to operate on isolated portions of very large configurations, prefer to break large configurations into several smaller configurations that can each be independently applied. You can use [data sources](https://opentofu.org/docs/v1.10/language/data-sources/) to access information about resources declared in other configurations, allowing a complex system architecture to be broken down into more manageable parts that can be updated independently. Other Options[​](https://opentofu.org/docs/v1.10/cli/commands/plan/#other-options "Direct link to Other Options") ------------------------------------------------------------------------------------------------------------------ The `tofu plan` command also has some other options that are related to the input and output of the planning command, rather than customizing what sort of plan OpenTofu will create. These commands are not necessarily also available on `tofu apply`, unless otherwise stated in the documentation for that command. The available options are: * `-compact-warnings` - Shows any warning messages in a compact form which includes only the summary messages, unless the warnings are accompanied by at least one error and thus the warning text might be useful context for the errors. * `-consolidate-warnings` - If OpenTofu produces any warnings, do not attempt to consolidate similar messages. All locations for all warnings will be listed. * `-consolidate-errors` - If OpenTofu produces any errors, attempt to consolidate similar messages into a single item. * `-detailed-exitcode` - Returns a detailed exit code when the command exits. When provided, this argument changes the exit codes and their meanings to provide more granular information about what the resulting plan contains: * 0 = Succeeded with empty diff (no changes) * 1 = Error * 2 = Succeeded with non-empty diff (changes present) * `-generate-config-out=PATH` - (Experimental) If `import` blocks are present in configuration, instructs OpenTofu to generate HCL for any imported resources not already present. The configuration is written to a new file at PATH, which must not already exist, or OpenTofu will error. If the plan fails for another reason, OpenTofu may still attempt to write configuration. * `-input=false` - Disables OpenTofu's default behavior of prompting for input for root module input variables that have not otherwise been assigned a value. This option is particularly useful when running OpenTofu in non-interactive automation systems. * `-json` - Enables the [machine readable JSON UI](https://opentofu.org/docs/internals/machine-readable-ui/) output. This implies `-input=false`, so the configuration must have no unassigned variable values to continue. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * `-no-color` - Disables terminal formatting sequences in the output. Use this if you are running OpenTofu in a context where its output will be rendered by a system that cannot interpret terminal formatting. * `-concise` - Disables progress-related messages in the output. * `-out=FILENAME` - Writes the generated plan to the given filename in an opaque file format that you can later pass to `tofu apply` to execute the planned changes, and to some other OpenTofu commands that can work with saved plan files. OpenTofu will allow any filename for the plan file, but a typical convention is to name it `tfplan`. **Do not** name the file with a suffix that OpenTofu recognizes as another file format; if you use a `.tf` or `.tofu` suffix then OpenTofu will try to interpret the file as a configuration source file, which will then cause syntax errors for subsequent commands. The generated file is not in any standard format intended for consumption by other software, but the file _does_ contain your full configuration, all of the values associated with planned changes, and all of the plan options including the input variables. If your plan includes any sort of sensitive data, even if obscured in OpenTofu's terminal output, it will be saved in cleartext in the plan file. You should therefore treat any saved plan files as potentially-sensitive artifacts. * `-parallelism=n` - Limit the number of concurrent operations as OpenTofu [walks the graph](https://opentofu.org/docs/v1.10/internals/graph/#walking-the-graph) . Defaults to 10. * `-state=statefile` - A legacy option used for the local backend only. Refer to the local backend's documentation for more information. * `-show-sensitive` - If specified, sensitive values will not be redacted in te UI output. * `-json` - Produce output in a machine-readable JSON format, suitable for use in text editor integrations and other automated systems. * `-deprecation` - Specify what type of warnings are shown. Accepted values: "module:all", "module:local", "module:none". Default: "module:all". When "module:all" is selected, OpenTofu will show the deprecation warnings for all modules. When "module:local" is selected, the warnings will be shown only for the modules that are imported with a relative path. When "module:none" is selected, all the deprecation warnings will be dropped. For configurations using [the `local` backend](https://opentofu.org/docs/v1.10/language/settings/backends/local/) only, `tofu plan` accepts the legacy command line option [`-state`](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) . ### Passing a Different Configuration Directory[​](https://opentofu.org/docs/v1.10/cli/commands/plan/#passing-a-different-configuration-directory "Direct link to Passing a Different Configuration Directory") If your workflow relies on overriding the root module directory, use [the `-chdir` global option](https://opentofu.org/docs/v1.10/cli/commands/#switching-working-directory-with-chdir) instead, which works across all commands and makes OpenTofu consistently look in the given directory for all files it would normally read or write in the current working directory. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/plan/#usage) * [Planning Modes](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-modes) * [Planning Options](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-options) * [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) * [Resource Targeting](https://opentofu.org/docs/v1.10/cli/commands/plan/#resource-targeting) * [Other Options](https://opentofu.org/docs/v1.10/cli/commands/plan/#other-options) * [Passing a Different Configuration Directory](https://opentofu.org/docs/v1.10/cli/commands/plan/#passing-a-different-configuration-directory) --- # OpenTofu Internals | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu Internals ================== This section covers the internals of OpenTofu and explains how plans are generated, the lifecycle of a provider, etc. The goal of this section is to remove any notion of "magic" from OpenTofu. We want you to be able to trust and understand what OpenTofu is doing to function. Note Knowledge of OpenTofu internals is not required to use OpenTofu. If you aren't interested in the internals of OpenTofu, you may safely skip this section. --- # Module Packages in OCI Registries | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Module Packages in OCI Registries ================================= OpenTofu supports installing module packages from [a variety of different sources](https://opentofu.org/docs/v1.10/language/modules/sources/) , including from repositories in registries that implement the OCI Distribution protocol. You can configure OpenTofu to install a module from an OCI repository by using the `oci:` source address scheme: Code Block module "example" { source = "oci://example.com/repository-name"} For more information on how to select OCI artifacts to install, refer to [the module sources documentation](https://opentofu.org/docs/v1.10/language/modules/sources/#oci-distribution-repository) . The remainder of this page focuses on how to construct suitable OCI artifacts for use as OpenTofu module packages. Required OCI Repository Content[​](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/#required-oci-repository-content "Direct link to Required OCI Repository Content") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The OCI artifact selected by an `oci:` module source address must follow certain requirements for both its manifest metadata and for the blob representing the content of the module package. The chosen tag or digest must correspond to a standard [OCI Image Manifest](https://github.com/opencontainers/image-spec/blob/v1.1.1/manifest.md) whose `artifactType` property is set to `"application/vnd.opentofu.modulepkg"`. The image manifest's `layers` array must include exactly one descriptor whose `mediaType` is `archive/zip`, referring to a valid `.zip` archive representing the content of the module package. The root directory of the `.zip` archive corresponds to the root directory of the module package, and so contains the `.tf`, `.tofu`, etc configuration files describing the default module from the module package. The archive may optionally contain subdirectories representing additional modules, which can then be selected using the usual syntax for [Modules in Package Sub-directories](https://opentofu.org/docs/v1.10/language/modules/sources/#modules-in-package-sub-directories) . If the specified source address does not include either of the `tag` or `digest` query string arguments then OpenTofu attempts to resolve a tag named `latest`. OpenTofu makes no other assumptions about tag naming convention beyond the syntax constraints required by the OCI Distribution specification. Assembling and Pushing Module Package Manifests[​](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/#assembling-and-pushing-module-package-manifests "Direct link to Assembling and Pushing Module Package Manifests") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### Install and Configure ORAS[​](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/#install-and-configure-oras "Direct link to Install and Configure ORAS") We recommend assembling and pushing the manifests and blobs for a module package using the CLI tool offered by [the ORAS project](https://oras.land/) . If you are installing and using ORAS for the first time, and you intend to push to an OCI registry that requires authentication, you will need to first obtain credentials for that repository using [`oras login`](https://oras.land/docs/commands/oras_login) . ### Create a `.zip` archive[​](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/#create-a-zip-archive "Direct link to create-a-zip-archive") The actual content of a module package is represented for an OCI artifact as a single layer using the `.zip` archive format. You can use any suitable tool to build a `.zip` archive containing the module source code (`.tf`/`.tofu`/etc files) you intend to distribute. For example, using the `zip` tool commonly available on Unix systems: Code Block zip -r ../module-package.zip . This command creates or updates an archive `module-package.zip` in the parent of the current working directory, containing all of the files in the current working directory and any of its subdirectories. Creating the file in the parent directory avoids adding the zip file into itself if you run the same command again. The next section will use `module-package.zip` to refer to the `.zip` archive you've created. ### Push the artifact to a remote repository[​](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/#push-the-artifact-to-a-remote-repository "Direct link to Push the artifact to a remote repository") The `oras push` command can automatically construct a suitable image manifest, upload that manifest and the associated `.zip` file to a remote OCI repository, and create or update one or more tags referring to it in the same repository. Code Block oras push \ --artifact-type=application/vnd.opentofu.modulepkg \ example.com/repository-name:latest \ module-package.zip:archive/zip `example.com/repository-name` is the address of the repository to push the artifact into. `latest` is the tag name to use. `module-package.zip` is the name of the `.zip` archive created in the previous step. The `:archive/zip` suffix tells ORAS which media type to specify for this file in the artifact manifest. OpenTofu does not support any other media types. The `--artifact-type` option included above must be used _exactly as shown_ to ensure that OpenTofu will recognize this artifact as a module package. The repository address and tag shown above can be specified in a `module` block source address as follows: Code Block module "example" { source = "oci://example.com/repository-name?tag=latest"} If you chose the tag name `latest` as shown here then you can omit the `tag` argument, specifying just `oci://example.com/repository-name`, because "latest" is the tag name OpenTofu uses by default. * [Required OCI Repository Content](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/#required-oci-repository-content) * [Assembling and Pushing Module Package Manifests](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/#assembling-and-pushing-module-package-manifests) * [Install and Configure ORAS](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/#install-and-configure-oras) * [Create a `.zip` archive](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/#create-a-zip-archive) * [Push the artifact to a remote repository](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/#push-the-artifact-to-a-remote-repository) --- # OCI Registry Credentials | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page OCI Registry Credentials ======================== All of the OpenTofu features which interact with OCI Registries use a centralized mechanism for obtaining credentials to use when making requests. Default Implicit Behavior[​](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/#default-implicit-behavior "Direct link to Default Implicit Behavior") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- By default, OpenTofu searches the following locations for "Docker-style" configuration files containing credentials, likely to have been issued by other software that interacts with OCI registries: * `$XDG_RUNTIME_DIR/containers/auth.json` (Linux only) * `$HOME/.config/containers/auth.json` (Windows and macOS only) * `$XDG_CONFIG_HOME/containers/auth.json` (`XDG_CONFIG_HOME` defaults to `$HOME/.config`) * `$HOME/.docker/config.json` * `$HOME/.dockercfg` In these files, OpenTofu expects to find configuration following the format specified in [`containers-auth.json`](https://github.com/containers/image/blob/22415d4f7ea9cd9ffbfc46bcf919137dabf0c3bb/docs/containers-auth.json.5.md) . Although you can hand-write these configuration files, the more common way to populate them is to run the "login" command of some other OCI-integrated software, such as `docker login`, `oras login`, `buildah login`, `skopeo login`, etc. All of those commands write the resulting credentials into one of the file paths listed above. OpenTofu selects the credentials associated with the pattern that most specifically matches the target repository address. For example, when making a request to a repository at `example.com/foo/bar`, OpenTofu prefers to use credentials configured for `example.com/foo` over credentials configured just for `example.com`. When there are multiple matching credentials of equal precedence, files earlier in the list above take priority over files later in the list. You can customize some aspects of this implicit credentials discovery behavior as part of [Default Credentials Configuration](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/#default-credentials-configuration) . Explicit Credentials Configuration[​](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/#explicit-credentials-configuration "Direct link to Explicit Credentials Configuration") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu also allows direct configuration of OCI Registry credentials as part of [the CLI configuration file](https://opentofu.org/docs/v1.10/cli/config/config-file/) , using `oci_credentials` blocks: Code Block oci_credentials "example.com" { username = "example" password = "example"} The label of each `oci_credentials` block must be an OCI registry domain name followed by an optional repository path prefix. For example, `example.com` matches all repositories on that registry, while `example.com/foo` only matches repositories whose name starts with a "foo" path segment. The content of an `oci_credentials` block has three forms depending on the kind of credentials and how they are specified: * **Inline username and password:** Use `username` and `password` arguments to directly specify credentials to use for authentication schemes like HTTP "Basic" authentication. When you specify a password directly you must protect your CLI Configuration file to avoid your secret password becoming compromised. * **Docker-style credential helper:** Use the `docker_credentials_helper` argument to specify the name of a program implementing the [Docker Credential Helper](https://github.com/docker/docker-credential-helpers) protocol, which OpenTofu then launches to obtain credentials only when they are needed. For example, if you work on macOS and install the `osxkeychain` credential helper then you can specify `docker_credentials_helper = "osxkeychain"` to make OpenTofu obtain credentials from your macOS Keychain. OpenTofu currently uses credential helpers only on a read-only basis, so any needed credentials must first be written into the underlying credential store using other software that has been configured to write credentials through the same credential helper. * **Inline OAuth credentials:** Use `access_token` and `refresh_token` arguments to directly specify OAuth-style credentials. When you specify an access token and refresh token directly you must protect your CLI Configuration file to avoid your tokens becoming compromised. When multiple `oci_credentials` blocks are present, OpenTofu selects the one whose block label most closely matches the target repository. By default, OpenTofu uses explicit `oci_credentials` blocks in conjunction with any automatically-discovered Docker-style configuration files, taking the most specific match across all of these sources. If the same repository address prefix is specified both in an explicit `oci_credentials` block and in a Docker-style configuration file then the explicit configuration takes priority. Default Credentials Configuration[​](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/#default-credentials-configuration "Direct link to Default Credentials Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The optional `oci_default_credentials` block type can appear at most once in the CLI configuration. When present, it customizes the [default implicit search behavior](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/#default-implicit-behavior) , or disables it entirely. The following arguments may appear in an `oci_default_credentials` block: * `discover_ambient_credentials`: Set this to `false` to completely disable all of the implicit search behavior, in which case only [explicit credentials configuration](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/#explicit-credentials-configuration) can be used. Defaults to `true`, which allows the implicit search behavior. * `docker_style_config_files`: A list of strings specifying filenames to treat as Docker-style configuration files, instead of the default search locations. Set `docker_style_config_files = []` to prevent searching for any Docker-style configuration files while still allowing discovery of other "ambient" credentials. Docker-style configuration files are currently the only available ambient credentials mechanism and so this is equivalent to `discover_ambient_credentials = false`, but that might change in future versions of OpenTofu. * `docker_credentials_helper`: Directly specifies the name of a global Docker-style credentials helper to use for all OCI repositories that are not matched by a more specific credentials configuration. For example, specify `docker_credentials_helper = "osxkeychain"` to make OpenTofu obtain credentials from your macOS Keychain. You must install the selected credential helper first so that OpenTofu can execute it. Note **OpenTofu does not use any credential helper unless explicitly configured to do so.** Docker CLI and some other more-closely-related software default to searching certain hard-coded credential helper names depending on your platform when no credential helper is configured and no static credentials are available. To avoid executing third-party software without explicit consent, OpenTofu instead requires that you directly configure any credential helper you intend to use, either by using this OpenTofu-specific setting or by using [the `"credsStore"` property](https://docs.docker.com/reference/cli/docker/#credential-store-options) in your Docker CLI configuration file. * [Default Implicit Behavior](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/#default-implicit-behavior) * [Explicit Credentials Configuration](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/#explicit-credentials-configuration) * [Default Credentials Configuration](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/#default-credentials-configuration) --- # Managing Plugins | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/plugins/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Managing Plugins ================ OpenTofu relies on plugins called "providers" in order to manage various types of resources. (For more information about providers, see [Providers](https://opentofu.org/docs/v1.10/language/providers/) in the OpenTofu language docs.) Note Providers are the only plugin type most OpenTofu users interact with. OpenTofu also supports third-party provisioner plugins, but we discourage their use. OpenTofu downloads and/or installs any providers [required](https://opentofu.org/docs/v1.10/language/providers/requirements/) by a configuration when [initializing](https://opentofu.org/docs/v1.10/cli/init/) a working directory. By default, this works without any additional interaction but requires network access to download providers from their source registry. You can configure OpenTofu's provider installation behavior to limit or skip network access, and to enable use of providers that aren't available via a networked source. OpenTofu also includes some commands to show information about providers and to reduce the effort of installing providers in airgapped environments. Configuring Plugin Installation[​](https://opentofu.org/docs/v1.10/cli/plugins/#configuring-plugin-installation "Direct link to Configuring Plugin Installation") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ OpenTofu's configuration file includes options for caching downloaded plugins, or explicitly specifying a local or HTTPS mirror to install plugins from. For more information, see [CLI Config File](https://opentofu.org/docs/v1.10/cli/config/config-file/) . Getting Plugin Information[​](https://opentofu.org/docs/v1.10/cli/plugins/#getting-plugin-information "Direct link to Getting Plugin Information") --------------------------------------------------------------------------------------------------------------------------------------------------- Use the [`tofu providers`](https://opentofu.org/docs/v1.10/cli/commands/providers/) command to get information about the providers required by the current working directory's configuration. Use the [`tofu version`](https://opentofu.org/docs/v1.10/cli/commands/version/) command (or `tofu -version`) to show the specific provider versions installed for the current working directory. Use the [`tofu providers schema`](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/) command to get machine-readable information about the resources and configuration options offered by each provider. Managing Plugin Installation[​](https://opentofu.org/docs/v1.10/cli/plugins/#managing-plugin-installation "Direct link to Managing Plugin Installation") --------------------------------------------------------------------------------------------------------------------------------------------------------- Use the [`tofu providers mirror`](https://opentofu.org/docs/v1.10/cli/commands/providers/mirror/) command to download local copies of every provider required by the current working directory's configuration. This directory will use the nested directory layout that OpenTofu expects when installing plugins from a local source, so you can transfer it directly to an airgapped system that runs OpenTofu. Use the [`tofu providers lock`](https://opentofu.org/docs/v1.10/cli/commands/providers/lock/) command to update the lock file that OpenTofu uses to ensure predictable runs when using ambiguous provider version constraints. * [Configuring Plugin Installation](https://opentofu.org/docs/v1.10/cli/plugins/#configuring-plugin-installation) * [Getting Plugin Information](https://opentofu.org/docs/v1.10/cli/plugins/#getting-plugin-information) * [Managing Plugin Installation](https://opentofu.org/docs/v1.10/cli/plugins/#managing-plugin-installation) --- # Credentials Helpers | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Credentials Helpers =================== For OpenTofu-specific features that interact with remote network services, such as module registries, OpenTofu by default looks for API credentials to use in these calls in [the CLI configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/) . Credentials helpers offer an alternative approach that allows you to customize how OpenTofu obtains credentials using an external program, which can then directly access an existing secrets management system in your organization. This page is about how to write and install a credentials helper. To learn how to configure a credentials helper that was already installed, see [the CLI config Credentials Helpers section](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials-helpers) . How OpenTofu finds Credentials Helpers[​](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#how-opentofu-finds-credentials-helpers "Direct link to How OpenTofu finds Credentials Helpers") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A credentials helper is a normal executable program that is installed in a particular location and whose name follows a specific naming convention. A credentials helper called "credstore", for example, would be implemented as an executable program named `terraform-credentials-credstore` (with an `.exe` extension on Windows only), and installed in one of the [default plugin search locations](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation) . How OpenTofu runs Credentials Helpers[​](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#how-opentofu-runs-credentials-helpers "Direct link to How OpenTofu runs Credentials Helpers") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Once OpenTofu has located the configured credentials helper, it will execute it once for each credentials request that cannot be satisfied by a `credentials` block in the CLI configuration. For the following examples, we'll assume a "credstore" credentials helper configured as follows: Code Block credentials_helper "credstore" { args = ["--host=credstore.example.com"]} OpenTofu runs the helper program with each of the arguments given in `args`, followed by an _verb_ and then the hostname that the verb will apply to. The current set of verbs are: * `get`: retrieve the credentials for the given hostname * `store`: store new credentials for the given hostname * `forget`: delete any stored credentials for the given hostname To represent credentials, the credentials helper protocol uses a JSON object whose contents correspond with the contents of [`credentials` blocks in the CLI configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials) . To represent an API token, the object contains a property called "token" whose value is the token string: Code Block { "token": "example-token-value"} The following sections describe the specific expected behaviors for each of the three verbs. `get`: retrieve the credentials for the given hostname[​](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#get-retrieve-the-credentials-for-the-given-hostname "Direct link to get-retrieve-the-credentials-for-the-given-hostname") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To retrieve credentials for `app.example.io`, OpenTofu would run the "credstore" helper as follows: Code Block terraform-credentials-credstore --host=credstore.example.com get app.example.io If the credentials helper is able to provide credentials for the given host then it must print a JSON credentials object to its stdout stream and then exit with status code zero to indicate success. If the credentials helper definitively has no credentials for the given host, then it must print an empty JSON object to stdout and exit with status zero. If the credentials helper is unable to provide the requested credentials for any other reason, it must print an end-user-oriented plain text error message to its stderr stream and then exit with a _non-zero_ status code. `store`: store new credentials for the given hostname[​](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#store-store-new-credentials-for-the-given-hostname "Direct link to store-store-new-credentials-for-the-given-hostname") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ To store new credentials for `app.example.io`, OpenTofu would run the "credstore" helper as follows: Code Block terraform-credentials-credstore --host=credstore.example.com store app.example.io OpenTofu then writes a JSON credentials object to the helper program's stdin stream. If the helper is able to store the given credentials then it must do so and then exit with status code zero and no output on stdout or stderr to indicate success. If it is unable to store the given credentials for any reason, it _must_ still fully read its stdin until EOF and then print an end-user-oriented plain text error message to its stderr stream before exiting with a non-zero status code. The new credentials must fully replace any existing credentials stored for the given hostname. `forget`: delete any stored credentials for the given hostname[​](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#forget-delete-any-stored-credentials-for-the-given-hostname "Direct link to forget-delete-any-stored-credentials-for-the-given-hostname") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To forget any existing credentials for `app.example.io`, OpenTofu would run the "credstore" helper as follows: Code Block terraform-credentials-credstore --host=credstore.example.com forget app.example.io No JSON credentials objects are used for the `forget` verb. If the helper program is able to delete its stored credentials for the given hostname or if there are no such credentials stored already then it must exist with status code zero and produce no output on stdout or stderr. If it is unable to forget the stored credentials for any reason, particularly if the helper cannot be sure that the credentials are no longer available for retrieval, the helper program must print an end-user-oriented plain text error message to its stderr stream and then exit with a non-zero status code. Handling Other Commands[​](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#handling-other-commands "Direct link to Handling Other Commands") ------------------------------------------------------------------------------------------------------------------------------------------------------------ The credentials helper protocol may be extended with additional verbs in future, so for forward-compatibility a credentials helper must react to any unsupported verb by printing an end-user-oriented plain text error message to its stderr stream and then exiting with a non-zero status code. Handling Unsupported Credentials Object Properties[​](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#handling-unsupported-credentials-object-properties "Direct link to Handling Unsupported Credentials Object Properties") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu defines only the `token` property within JSON credentials objects. If a credentials helper is asked to store an object that has any properties other than `token` and if it is not able to faithfully retain them then it must behave as if the object is unstorable, returning an error. It must _not_ store the `token` value in isolation and silently drop other properties, as that might change the meaning of the credentials object. If technically possible within the constraints of the target system, a credentials helper should prefer to store the whole JSON object as-is for later retrieval. For systems that are more constrained, it's acceptable to store only the `token` string so long as the program rejects objects containing other properties as described above. Installing a Credentials Helper[​](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#installing-a-credentials-helper "Direct link to Installing a Credentials Helper") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ OpenTofu does not have any automatic installation mechanism for credentials helpers. Instead, the user must extract the helper program executable into one of the [default plugin search locations](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation) . If you are packaging a credentials helper for distribution, place it in an named with the expected naming scheme (`terraform-credentials-example`) and, if the containing archive format supports it and it's meaningful for the target operating system, mark the file as executable to increase the chances that it will work immediately after extraction. OpenTofu does _not_ honor the `-plugin-dir` argument to `tofu init` when searching for credentials helpers, because credentials are also used by other commands that can be run prior to `tofu init`. Only the default search locations are supported. * [How OpenTofu finds Credentials Helpers](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#how-opentofu-finds-credentials-helpers) * [How OpenTofu runs Credentials Helpers](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#how-opentofu-runs-credentials-helpers) * [`get`: retrieve the credentials for the given hostname](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#get-retrieve-the-credentials-for-the-given-hostname) * [`store`: store new credentials for the given hostname](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#store-store-new-credentials-for-the-given-hostname) * [`forget`: delete any stored credentials for the given hostname](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#forget-delete-any-stored-credentials-for-the-given-hostname) * [Handling Other Commands](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#handling-other-commands) * [Handling Unsupported Credentials Object Properties](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#handling-unsupported-credentials-object-properties) * [Installing a Credentials Helper](https://opentofu.org/docs/v1.10/internals/credentials-helpers/#installing-a-credentials-helper) --- # Debugging OpenTofu | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/debugging/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Debugging OpenTofu ================== OpenTofu has detailed logs that you can enable by setting the `TF_LOG` environment variable to any value. Enabling this setting causes detailed logs to appear on `stderr`. You can set `TF_LOG` to one of the log levels (in order of decreasing verbosity) `TRACE`, `DEBUG`, `INFO`, `WARN` or `ERROR` to change the verbosity of the logs. Warning Logs produced with the `TRACE` level may contain sensitive details such as credentials and should be treated with care. Setting `TF_LOG` to `JSON` outputs logs at the `TRACE` level or higher, and uses a parseable JSON encoding as the formatting. Warning The JSON encoding of log files is not considered a stable interface. It may change at any time, without warning. It is meant to support tooling that will be forthcoming, and that tooling is the only supported way to interact with JSON formatted logs. Logging can be enabled separately for tofu itself and the provider plugins using the `TF_LOG_CORE` or `TF_LOG_PROVIDER` environment variables. These take the same level arguments as `TF_LOG`, but only activate a subset of the logs. To persist logged output you can set `TF_LOG_PATH` in order to force the log to always be appended to a specific file when logging is enabled. Note that even when `TF_LOG_PATH` is set, `TF_LOG` must be set in order for any logging to be enabled. If you find a bug with OpenTofu, please include the detailed log by using a service such as gist. --- # Recovering from State Disasters | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/state/recover/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Recovering from State Disasters =============================== If something has gone horribly wrong (possibly due to accidents when performing other state manipulation actions), you might need to take drastic actions with your state data. * [The `tofu force-unlock` command](https://opentofu.org/docs/v1.10/cli/commands/force-unlock/) can override the protections OpenTofu uses to prevent two processes from modifying state at the same time. You might need this if a OpenTofu process (like a normal apply) is unexpectedly terminated (like by the complete destruction of the VM it's running in) before it can release its lock on the state backend. Do not run this until you are completely certain what happened to the process that caused the lock to get stuck. * [The `tofu state pull` command](https://opentofu.org/docs/v1.10/cli/commands/state/pull/) and [the `tofu state push` command](https://opentofu.org/docs/v1.10/cli/commands/state/push/) can directly read and write entire state files from and to the configured backend. You might need this for obtaining or restoring a state backup. --- # Moving Resources | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/state/move/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Moving Resources ================ OpenTofu's state associates each real-world object with a configured resource at a specific [resource address](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/) . This is seamless when changing a resource's attributes, but OpenTofu will lose track of a resource if you change its name, move it to a different module, or change its provider. Usually that's fine: OpenTofu will destroy the old resource, replace it with a new one (using the new resource address), and update any resources that rely on its attributes. In cases where it's important to preserve an existing infrastructure object, you can explicitly tell OpenTofu to associate it with a different configured resource. For most cases we recommend using [the OpenTofu language's refactoring features](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/) to document in your module exactly how the resource names have changed over time. OpenTofu reacts to this information automatically during planning, so users of your module do not need to take any unusual extra steps. There are some other situations which require explicit state modifications, though. For those, consider the following OpenTofu commands: * [The `tofu state mv` command](https://opentofu.org/docs/v1.10/cli/commands/state/mv/) changes which resource address in your configuration is associated with a particular real-world object. Use this to preserve an object when renaming a resource, or when moving a resource into or out of a child module. * [The `tofu state rm` command](https://opentofu.org/docs/v1.10/cli/commands/state/rm/) tells OpenTofu to stop managing a resource as part of the current working directory and workspace, _without_ destroying the corresponding real-world object. (You can later use `tofu import` to start managing that resource in a different workspace or a different OpenTofu configuration.) * [The `tofu state replace-provider` command](https://opentofu.org/docs/v1.10/cli/commands/state/replace-provider/) transfers existing resources to a new provider without requiring them to be re-created. --- # CLI Configuration File | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/config/config-file/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page CLI Configuration File (`.tofurc` or `tofu.rc`) =============================================== The CLI configuration file configures per-user settings for CLI behaviors, which apply across all OpenTofu working directories. This is separate from [your infrastructure configuration](https://opentofu.org/docs/v1.10/language/) . Locations[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#locations "Direct link to Locations") ----------------------------------------------------------------------------------------------------------- The configuration can be placed in a single file whose location depends on the host operating system: * On Windows, the file must be named `tofu.rc` and placed in the relevant user's `%APPDATA%` directory. The physical location of this directory depends on your Windows version and system configuration; use `$env:APPDATA` in PowerShell to find its location on your system. The `terraform.rc` is supported for backward-compatibility purposes. If both `terraform.rc` and `tofu.rc` files exists, the later would take precedence. * On all other systems, the file must be named `.tofurc` (note the leading period) and placed directly in the home directory of the relevant user or be named `tofurc` and placed in a valid [XDG Base Directory](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) config directory such as `$XDG_CONFIG_HOME/opentofu`. The `.terraformrc` is supported for backward-compatibility purposes. If both `.terraformrc` and `.tofurc` files exists, the latter would take precedence. When using an XDG config directory `.terraformrc` and `terraformrc` are ignored. On Windows, beware of Windows Explorer's default behavior of hiding filename extensions. OpenTofu will not recognize a file named `tofuc.rc.txt` as a CLI configuration file, even though Windows Explorer may _display_ its name as just `tofu.rc`. Use `dir` from PowerShell or Command Prompt to confirm the filename. The location of the OpenTofu CLI configuration file can also be specified using the `TF_CLI_CONFIG_FILE` [environment variable](https://opentofu.org/docs/v1.10/cli/config/environment-variables/) . Any such file should follow the naming pattern `*.tfrc`. Configuration File Syntax[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#configuration-file-syntax "Direct link to Configuration File Syntax") ----------------------------------------------------------------------------------------------------------------------------------------------------------- The configuration file uses the same _HCL_ syntax as `.tf` and `.tofu` files, but with different attributes and blocks. The following example illustrates the general syntax; see the following section for information on the meaning of each of these settings: Code Block plugin_cache_dir = "$HOME/.terraform.d/plugin-cache" Available Settings[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#available-settings "Direct link to Available Settings") -------------------------------------------------------------------------------------------------------------------------------------- The following settings can be set in the CLI configuration file: * `credentials` - configures credentials for use with a cloud backend. See [Credentials](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials) below for more information. * `credentials_helper` - configures an external helper program for the storage and retrieval of credentials for cloud backends. See [Credentials Helpers](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials-helpers) below for more information. * `oci_credentials` and `default_oci_credentials` - configures credentials for interacting with an OCI Registry. Refer to [OCI Registry Credentials](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/) for more information. * `plugin_cache_dir` β€” enables [plugin caching](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-plugin-cache) and specifies, as a string, the location of the plugin cache directory. * `provider_installation` - customizes the installation methods used by `tofu init` when installing provider plugins. See [Provider Installation](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation) below for more information. Credentials[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials "Direct link to Credentials") ----------------------------------------------------------------------------------------------------------------- When interacting with OpenTofu-specific network services, OpenTofu expects to find API tokens in CLI configuration files in `credentials` blocks: Code Block credentials "app.opentofu.org" { token = "xxxxxx.atlasv1.zzzzzzzzzzzzz"} If you are running the OpenTofu CLI interactively on a computer with a web browser, you can use [the `tofu login` command](https://opentofu.org/docs/v1.10/cli/commands/login/) to get credentials and automatically save them in the CLI configuration. If not, you can manually write `credentials` blocks. You can have multiple `credentials` blocks if you regularly use services from multiple hosts. Each `credentials` block contains a `token` argument giving the API token to use for that host. Note The credentials hostname must match the hostname in your module sources and/or backend configuration. `credentials` blocks are used only for OpenTofu-specific protocols. You can configure credentials for OCI Registries using `oci_credentials` blocks, as described in [OCI Registry Credentials](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/) . ### Environment Variable Credentials[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#environment-variable-credentials "Direct link to Environment Variable Credentials") If you would prefer not to store your API tokens directly in the CLI configuration, you may use a host-specific environment variable. Environment variable names should have the prefix `TF_TOKEN_` added to the domain name, with periods encoded as underscores. For example, the value of a variable named `TF_TOKEN_app_opentofu_org` will be used as a bearer authorization token when the CLI makes service requests to the hostname `app.opentofu.org`. You must convert domain names containing non-ASCII characters to their [punycode equivalent](https://www.charset.org/punycode) with an ACE prefix. For example, token credentials for δΎ‹γˆγ°.com must be set in a variable called `TF_TOKEN_xn--r8j3dr99h_com`. Hyphens are also valid within host names but usually invalid as variable names and may be encoded as double underscores. For example, you can set a token for the domain name `cafΓ©.fr` as `TF_TOKEN_xn--caf-dma.fr`, `TF_TOKEN_xn--caf-dma_fr`, or `TF_TOKEN_xn____caf__dma_fr`. If multiple variables evaluate to the same hostname, OpenTofu will choose the one defined last in the operating system's variable table. ### Credentials Helpers[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials-helpers "Direct link to Credentials Helpers") You can configure a `credentials_helper` to instruct OpenTofu to use a different credentials storage mechanism. Code Block credentials_helper "example" { args = []} `credentials_helper` is a configuration block that can appear at most once in the CLI configuration. Its label (`"example"` above) is the name of the credentials helper to use. The `args` argument is optional and allows passing additional arguments to the helper program, for example if it needs to be configured with the address of a remote host to access for credentials. A configured credentials helper will be consulted only to retrieve credentials for hosts that are _not_ explicitly configured in a `credentials` block as described in the previous section. Conversely, this means you can override the credentials returned by the helper for a specific hostname by writing a `credentials` block alongside the `credentials_helper` block. OpenTofu does not include any credentials helpers in the main distribution. To learn how to write and install your own credentials helpers to integrate with existing in-house credentials management systems, see [the guide to Credentials Helper internals](https://opentofu.org/docs/v1.10/internals/credentials-helpers/) . ### Credentials Source Priority Order[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials-source-priority-order "Direct link to Credentials Source Priority Order") Credentials found in an environment variable for a particular service host as described above will be preferred over those in CLI config as set by `tofu login`. If neither are set, any configured credentials helper will be consulted. Provider Installation[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation "Direct link to Provider Installation") ----------------------------------------------------------------------------------------------------------------------------------------------- The default way to install provider plugins is from a provider registry. The origin registry for a provider is encoded in the provider's source address, like `registry.opentofu.org/hashicorp/aws`. For convenience in the common case, OpenTofu allows omitting the hostname portion for providers on `registry.opentofu.org`, so you can write shorter public provider addresses like `hashicorp/aws`. Downloading a plugin directly from its origin registry is not always appropriate, though. For example, the system where you are running OpenTofu may not be able to access an origin registry due to firewall restrictions within your organization or your locality. To allow using OpenTofu providers in these situations, there are some alternative options for making provider plugins available to OpenTofu which we'll describe in the following sections. ### Explicit Installation Method Configuration[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#explicit-installation-method-configuration "Direct link to Explicit Installation Method Configuration") A `provider_installation` block in the CLI configuration allows overriding OpenTofu's default installation behaviors, so you can force OpenTofu to use a local mirror for some or all of the providers you intend to use. The general structure of a `provider_installation` block is as follows: Code Block provider_installation { filesystem_mirror { path = "/usr/share/terraform/providers" include = ["example.com/*/*"] } direct { exclude = ["example.com/*/*"] }} Each of the nested blocks inside the `provider_installation` block specifies one installation method. Each installation method can take both `include` and `exclude` patterns that specify which providers a particular installation method can be used for. In the example above, we specify that any provider whose origin registry is at `example.com` can be installed only from the filesystem mirror at `/usr/share/terraform/providers`, while all other providers can be installed only directly from their origin registries. If you set both `include` and `exclude` for a particular installation method, the exclusion patterns take priority. For example, including `registry.opentofu.org/hashicorp/*` but also excluding `registry.opentofu.org/hashicorp/dns` will make that installation method apply to everything in the `hashicorp` namespace with the exception of `hashicorp/dns`. As with provider source addresses in the main configuration, you can omit the `registry.opentofu.org/` prefix for providers distributed through the public OpenTofu Registry, even when using wildcards. For example, `registry.opentofu.org/hashicorp/*` and `hashicorp/*` are equivalent. `*/*` is a shorthand for `registry.opentofu.org/*/*`, not for `*/*/*`. The following are the supported installation method types: * `direct`: request information about the provider directly from its origin registry and download over the network from the location that registry indicates. This method expects no additional arguments. * `filesystem_mirror`: consult a directory on the local disk for copies of providers. This method requires the additional argument `path` to indicate which directory to look in. OpenTofu expects the given directory to contain a nested directory structure where the path segments together provide metadata about the available providers. The following two directory structures are supported: * Packed layout: `HOSTNAME/NAMESPACE/TYPE/terraform-provider-TYPE_VERSION_TARGET.zip` is the distribution zip file obtained from the provider's origin registry. * Unpacked layout: `HOSTNAME/NAMESPACE/TYPE/VERSION/TARGET` is a directory containing the result of extracting the provider's distribution zip file. In both layouts, the `VERSION` is a string like `2.0.0` and the `TARGET` specifies a particular target platform using a format like `darwin_amd64`, `linux_arm`, `windows_amd64`, etc. If you use the unpacked layout, OpenTofu will attempt to create a symbolic link to the mirror directory when installing the provider, rather than creating a deep copy of the directory. The packed layout prevents this because OpenTofu must extract the zip file during installation. You can include multiple `filesystem_mirror` blocks in order to specify several different directories to search. * `network_mirror`: consult a particular HTTPS server for copies of providers, regardless of which registry host they belong to. This method requires the additional argument `url` to indicate the mirror base URL, which should use the `https:` scheme and end with a trailing slash. OpenTofu expects the given URL to be a base URL for an implementation of [the provider network mirror protocol](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/) , which is designed to be relatively easy to implement using typical static website hosting mechanisms. * `oci_mirror`: map provider source addresses into OCI repository addresses, regardless of which registry host they belong to, and then retrieve them using the OCI Distribution protocol. This is similar to `network_mirror`, but uses the industry-standard OCI registry protocol instead of the OpenTofu-specific provider network mirror protocol to allow you to reuse a pre-existing OCI registry service. For more information, refer to [Provider Mirrors in OCI Registries](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/) . Warning Don't configure `network_mirror` URLs that you do not trust. Provider mirror servers are subject to TLS certificate checks to verify identity, but a network mirror with a TLS certificate can potentially serve modified copies of upstream providers with malicious content. OpenTofu will try all of the specified methods whose include and exclude patterns match a given provider, and select the newest version available across all of those methods that matches the version constraint given in each OpenTofu configuration. If you have a local mirror of a particular provider and intend OpenTofu to use that local mirror exclusively, you must either remove the `direct` installation method altogether or use its `exclude` argument to disable its use for specific providers. ### Implied Local Mirror Directories[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#implied-local-mirror-directories "Direct link to Implied Local Mirror Directories") If your CLI configuration does not include a `provider_installation` block at all, OpenTofu produces an _implied_ configuration. The implied configuration includes a selection of `filesystem_mirror` methods and then the `direct` method. The set of directories OpenTofu can select as filesystem mirrors depends on the operating system where you are running OpenTofu: * **Windows:** `%APPDATA%/terraform.d/plugins` and `%APPDATA%/HashiCorp/Terraform/plugins` * **Mac OS X:** `$HOME/.terraform.d/plugins`, `~/Library/Application Support/io.terraform/plugins`, and `/Library/Application Support/io.terraform/plugins` * **Linux and other Unix-like systems**:`$HOME/.terraform.d/plugins` and `opentofu/plugins` located within a valid [XDG Base Directory](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) data directory such as `$XDG_DATA_HOME/opentofu/plugins`. If a `terraform.d/plugins` directory exists in the current working directory then OpenTofu will also include that directory, regardless of your operating system. This behavior changes when you use the `-chdir` option with the `init` command. In that case, OpenTofu checks for the `terraform.d/plugins` directory in the launch directory and not in the directory you specified with `-chdir`. OpenTofu will check each of the paths above to see if it exists, and if so treat it as a filesystem mirror. The directory structure inside each one must therefore match one of the two structures described for `filesystem_mirror` blocks in [Explicit Installation Method Configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#explicit-installation-method-configuration) . In addition to the zero or more implied `filesystem_mirror` blocks, OpenTofu also creates an implied `direct` block. OpenTofu will scan all of the filesystem mirror directories to see which providers are placed there and automatically exclude all of those providers from the implied `direct` block. (This automatic `exclude` behavior applies only to _implicit_ `direct` blocks; if you use explicit `provider_installation` you will need to write the intended exclusions out yourself.) ### Provider Plugin Cache[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-plugin-cache "Direct link to Provider Plugin Cache") By default, `tofu init` downloads plugins into a subdirectory of the working directory so that each working directory is self-contained. As a consequence, if you have multiple configurations that use the same provider then a separate copy of its plugin will be downloaded for each configuration. Given that provider plugins can be quite large (on the order of hundreds of megabytes), this default behavior can be inconvenient for those with slow or metered Internet connections. Therefore OpenTofu optionally allows the use of a local directory as a shared plugin cache, which then allows each distinct plugin binary to be downloaded only once. To enable the plugin cache, use the `plugin_cache_dir` setting in the CLI configuration file. For example: Code Block plugin_cache_dir = "$HOME/.terraform.d/plugin-cache" This directory must already exist before OpenTofu will cache plugins; OpenTofu will not create the directory itself. Please note that on Windows it is necessary to use forward slash separators (`/`) rather than the conventional backslash (`\`) since the configuration file parser considers a backslash to begin an escape sequence. Setting this in the configuration file is the recommended approach for a persistent setting. Alternatively, the `TF_PLUGIN_CACHE_DIR` environment variable can be used to enable caching or to override an existing cache directory within a particular shell session: Code Block export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache" When a plugin cache directory is enabled, the `tofu init` command will still use the configured or implied installation methods to obtain metadata about which plugins are available, but once a suitable version has been selected it will first check to see if the chosen plugin is already available in the cache directory. If so, OpenTofu will use the previously-downloaded copy. If the selected plugin is not already in the cache, OpenTofu will download it into the cache first and then copy it from there into the correct location under your current working directory. When possible OpenTofu will use symbolic links to avoid storing a separate copy of a cached plugin in multiple directories. The plugin cache directory _must not_ also be one of the configured or implied filesystem mirror directories, since the cache management logic conflicts with the filesystem mirror logic when operating on the same directory. OpenTofu will never itself delete a plugin from the plugin cache once it has been placed there. Over time, as plugins are upgraded, the cache directory may grow to contain several unused versions which you must delete manually. Note The plugin cache directory makes a best effort to be concurrency safe. It uses standard file locking practices (fnctl flock or LockFileEx), which have different guarantees depending on Operating System and filesystem. ### Allowing the Provider Plugin Cache to break the dependency lock file[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#allowing-the-provider-plugin-cache-to-break-the-dependency-lock-file "Direct link to Allowing the Provider Plugin Cache to break the dependency lock file") Note The option described in is for unusual and exceptional situations only. Do not set this option unless you are sure you need it and you fully understand the consequences of enabling it. By default OpenTofu will use packages from the global cache directory only if they match at least one of the checksums recorded in the [dependency lock file](https://opentofu.org/docs/v1.10/language/files/dependency-lock/) for that provider. This ensures that OpenTofu can always generate a complete and correct dependency lock file entry the first time you use a new provider in a particular configuration. However, we know that in some special situations teams have been unable to use the dependency lock file as intended, and so they don't include it in their version control as recommended and instead let OpenTofu re-generate it each time it installs providers. For those teams that don't preserve the dependency lock file in their version control systems between runs, OpenTofu allows an additional CLI Configuration setting which tells OpenTofu to always treat a package in the cache directory as valid even if there isn't already an entry in the dependency lock file to confirm it: Code Block plugin_cache_may_break_dependency_lock_file = true Alternatively, you can set the environment variable `TF_PLUGIN_CACHE_MAY_BREAK_DEPENDENCY_LOCK_FILE` to any value other than the empty string or `0`, which is equivalent to the above setting. Setting this option gives OpenTofu CLI permission to create an incomplete dependency lock file entry for a provider if that would allow OpenTofu to use the cache to install that provider. In that situation the dependency lock file will be valid for use on the current system but may not be valid for use on another computer with a different operating system or CPU architecture, because it will include only a checksum of the package in the global cache. We recommend that most users leave this option unset, in which case OpenTofu will always install a provider from upstream the first time you use it with a particular configuration, but can then re-use the cache entry on later runs once the dependency lock file records valid checksums for the provider package. Note The OpenTofu team intends to improve the dependency lock file mechanism in future versions so that it will be usable in more situations. At that time this option will become silently ignored. If your workflow relies on the use of this option, please open a GitHub issue to share details about your situation so that we can consider how to support it without breaking the dependency lock file. ### Development Overrides for Provider Developers[​](https://opentofu.org/docs/v1.10/cli/config/config-file/#development-overrides-for-provider-developers "Direct link to Development Overrides for Provider Developers") Normally OpenTofu verifies version selections and checksums for providers in order to help ensure that all operations are made with the intended version of a provider, and that authors can gradually upgrade to newer provider versions in a controlled manner. These version and checksum rules are inconvenient when developing a provider though, because we often want to try a test configuration against a development build of a provider that doesn't even have an associated version number yet, and doesn't have an official set of checksums listed in a provider registry. As a convenience for provider development, OpenTofu supports a special additional block `dev_overrides` in `provider_installation` blocks. The contents of this block effectively override all of the other configured installation methods, so a block of this type must always appear first in the sequence: Code Block provider_installation { # Use /home/developer/tmp/terraform-null as an overridden package directory # for the hashicorp/null provider. This disables the version and checksum # verifications for this provider and forces OpenTofu to look for the # null provider plugin in the given directory. dev_overrides { "hashicorp/null" = "/home/developer/tmp/terraform-null" } # For all other providers, install them directly from their origin provider # registries as normal. If you omit this, OpenTofu will _only_ use # the dev_overrides block, and so no other providers will be available. direct {}} With development overrides in effect, the `tofu init` command will still attempt to select a suitable published version of your provider to install and record in [the dependency lock file](https://opentofu.org/docs/v1.10/language/files/dependency-lock/) for future use, but other commands like `tofu apply` will disregard the lock file's entry for `hashicorp/null` and will use the given directory instead. Once your new changes are included in a published release of the provider, you can use `tofu init -upgrade` to select the new version in the dependency lock file and remove your development override. The override path for a particular provider should be a directory similar to what would be included in a `.zip` file when distributing the provider. At minimum that includes an executable file named with a prefix like `terraform-provider-null`, where `null` is the provider type. If your provider makes use of other files in its distribution package then you can copy those files into the override directory too. You may wish to enable a development override only for shell sessions where you are actively working on provider development. If so, you can write a local CLI configuration file with content like the above in your development directory, perhaps called `dev.tfrc` for the sake of example, and then use the `TF_CLI_CONFIG_FILE` environment variable to instruct OpenTofu to use that localized CLI configuration instead of the default one: Code Block export TF_CLI_CONFIG_FILE=/home/developer/tmp/dev.tfrc Development overrides are not intended for general use as a way to have OpenTofu look for providers on the local filesystem. If you wish to put copies of _released_ providers in your local filesystem, see [Implied Local Mirror Directories](https://opentofu.org/docs/v1.10/cli/config/config-file/#implied-local-mirror-directories) or [Explicit Installation Method Configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#explicit-installation-method-configuration) instead. This development overrides mechanism is intended as a pragmatic way to enable smoother provider development. The details of how it behaves, how to configure it, and how it interacts with the dependency lock file may all evolve in future OpenTofu releases, including possible breaking changes. We therefore recommend using development overrides only temporarily during provider development work. * [Locations](https://opentofu.org/docs/v1.10/cli/config/config-file/#locations) * [Configuration File Syntax](https://opentofu.org/docs/v1.10/cli/config/config-file/#configuration-file-syntax) * [Available Settings](https://opentofu.org/docs/v1.10/cli/config/config-file/#available-settings) * [Credentials](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials) * [Environment Variable Credentials](https://opentofu.org/docs/v1.10/cli/config/config-file/#environment-variable-credentials) * [Credentials Helpers](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials-helpers) * [Credentials Source Priority Order](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials-source-priority-order) * [Provider Installation](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation) * [Explicit Installation Method Configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#explicit-installation-method-configuration) * [Implied Local Mirror Directories](https://opentofu.org/docs/v1.10/cli/config/config-file/#implied-local-mirror-directories) * [Provider Plugin Cache](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-plugin-cache) * [Allowing the Provider Plugin Cache to break the dependency lock file](https://opentofu.org/docs/v1.10/cli/config/config-file/#allowing-the-provider-plugin-cache-to-break-the-dependency-lock-file) * [Development Overrides for Provider Developers](https://opentofu.org/docs/v1.10/cli/config/config-file/#development-overrides-for-provider-developers) --- # Inspecting State | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/state/inspect/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Inspecting State ================ OpenTofu includes some commands for reading and updating state without taking any other actions. * [The `tofu state list` command](https://opentofu.org/docs/v1.10/cli/commands/state/list/) shows the resource addresses for every resource OpenTofu knows about in a configuration, optionally filtered by partial resource address. * [The `tofu state show` command](https://opentofu.org/docs/v1.10/cli/commands/state/show/) displays detailed state data about one resource. * [The `tofu refresh` command](https://opentofu.org/docs/v1.10/cli/commands/refresh/) updates state data to match the real-world condition of the managed resources. This is done automatically during plans and applies, but not when interacting with state directly. --- # Manipulating OpenTofu State | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/state/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Manipulating OpenTofu State =========================== OpenTofu uses [state data](https://opentofu.org/docs/v1.10/language/state/) to remember which real-world object corresponds to each resource in the configuration; this allows it to modify an existing object when its resource declaration changes. OpenTofu updates state automatically during plans and applies. However, it's sometimes necessary to make deliberate adjustments to OpenTofu's state data, usually to compensate for changes to the configuration or the real managed infrastructure. OpenTofu CLI supports several workflows for interacting with state: * [Inspecting State](https://opentofu.org/docs/v1.10/cli/state/inspect/) * [Forcing Re-creation](https://opentofu.org/docs/v1.10/cli/state/taint/) * [Moving Resources](https://opentofu.org/docs/v1.10/cli/state/move/) * Importing Pre-existing Resources (documented in the [Importing Infrastructure](https://opentofu.org/docs/v1.10/cli/import/) section) * [Disaster Recovery](https://opentofu.org/docs/v1.10/cli/state/recover/) Important Modifying state data outside a normal plan or apply can cause OpenTofu to lose track of managed resources, which might waste money, annoy your colleagues, or even compromise the security of your operations. Make sure to keep backups of your state data when modifying state out-of-band. --- # Command: state push | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/state/push/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state push =================== The `tofu state push` command is used to manually upload a local state file to [remote state](https://opentofu.org/docs/v1.10/language/state/remote/) . This command also works with local state. This command should rarely be used. It is meant only as a utility in case manual intervention is necessary with the remote state. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/state/push/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------ Usage: `tofu state push [options] PATH` This command pushes the state specified by PATH to the currently configured [backend](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) . If PATH is "-" then the state data to push is read from stdin. This data is loaded completely into memory and verified prior to being written to the destination state. Note OpenTofu state files must be in UTF-8 format without a byte order mark (BOM). For PowerShell on Windows, use `Set-Content` to automatically encode files in UTF-8 format. For example, run `tofu state push | sc terraform.tfstate`. OpenTofu will perform a number of safety checks to prevent you from making changes that appear to be unsafe: * **Differing lineage**: If the "lineage" value in the state differs, OpenTofu will not allow you to push the state. A differing lineage suggests that the states are completely different and you may lose data. * **Higher remote serial**: If the "serial" value in the destination state is higher than the state being pushed, OpenTofu will prevent the push. A higher serial suggests that data is in the destination state that isn't accounted for in the local state being pushed. Both of these safety checks can be disabled with the `-force` flag. **This is not recommended.** If you disable the safety checks and are pushing state, the destination state will be overwritten. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.10/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.10/language/settings/backends/remote/) only, `tofu state push` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/cli/cloud/command-line-arguments/#ignore-remote-version) . Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu state push`. This command also accepts the following options for tofu state push: * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * [`ignore-remote-version`](https://opentofu.org/docs/v1.10/cli/cloud/command-line-arguments/#ignore-remote-version) . * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/state/push/#usage) --- # Command: state pull | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/state/pull/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state pull =================== The `tofu state pull` command is used to manually download and output the state from [remote state](https://opentofu.org/docs/v1.10/language/state/remote/) . This command also works with local state. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/state/pull/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------ Usage: `tofu state pull` This command downloads the state from its current location, upgrades the local copy to the latest state file version that is compatible with locally-installed OpenTofu, and outputs the raw format to stdout. This is useful for reading values out of state (potentially pairing this command with something like [jq](https://stedolan.github.io/jq/) ). It is also useful if you need to make manual modifications to state. You cannot use this command to inspect the OpenTofu version of the remote state, as it will always be converted to the current OpenTofu version before output. Note OpenTofu state files must be in UTF-8 format without a byte order mark (BOM). For PowerShell on Windows, use `Set-Content` to automatically encode files in UTF-8 format. For example, run `tofu state pull | sc terraform.tfstate`. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu state pull`. The command support the following command-line arguments: * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/state/pull/#usage) --- # Command: state replace-provider | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/state/replace-provider/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state replace-provider =============================== The `tofu state replace-provider` command is used to replace the provider for resources in a [OpenTofu state](https://opentofu.org/docs/v1.10/language/state/) . Usage[​](https://opentofu.org/docs/v1.10/cli/commands/state/replace-provider/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------------------ Usage: `tofu state replace-provider [options] FROM_PROVIDER_FQN TO_PROVIDER_FQN` This command will update all resources using the "from" provider, setting the provider to the specified "to" provider. This allows changing the source of a provider which currently has resources in state. This command will output a backup copy of the state prior to saving any changes. The backup cannot be disabled. Due to the destructive nature of this command, backups are required. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu state replace-providers`. This command also accepts the following options: * `-auto-approve` - Skip interactive approval. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=0s` - Duration to retry a state lock. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.10/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.10/language/settings/backends/remote/) only, `tofu state replace-provider` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/v1.10/cli/cloud/command-line-arguments/#ignore-remote-version) . For configurations using [the `local` state](https://opentofu.org/docs/v1.10/language/settings/backends/local/) only, `tofu state replace-provider` also accepts the legacy options [`-state`, `-state-out`, and `-backup`](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) . Example[​](https://opentofu.org/docs/v1.10/cli/commands/state/replace-provider/#example "Direct link to Example") ------------------------------------------------------------------------------------------------------------------ The example below replaces the `hashicorp/aws` provider with a fork by `acme`, hosted at a private registry at `registry.acme.corp`: Code Block $ tofu state replace-provider hashicorp/aws registry.acme.corp/acme/aws * [Usage](https://opentofu.org/docs/v1.10/cli/commands/state/replace-provider/#usage) * [Example](https://opentofu.org/docs/v1.10/cli/commands/state/replace-provider/#example) --- # Command: taint | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/taint/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: taint ============== The `tofu taint` command informs OpenTofu that a particular object has become degraded or damaged. OpenTofu represents this by marking the object as "tainted" in the OpenTofu state, and OpenTofu will propose to replace it in the next plan you create. Warning This command is deprecated, we recommend using the `-replace` option with `tofu apply` instead (details below). Recommended Alternative[​](https://opentofu.org/docs/v1.10/cli/commands/taint/#recommended-alternative "Direct link to Recommended Alternative") ------------------------------------------------------------------------------------------------------------------------------------------------- We recommend using the [`-replace` option](https://opentofu.org/docs/v1.10/cli/commands/plan/#replace-address) with `tofu apply` to force OpenTofu to replace an object even though there are no configuration changes that would require it. Code Block $ tofu apply -replace="aws_instance.example[0]" We recommend the `-replace` option because the change will be reflected in the OpenTofu plan, letting you understand how it will affect your infrastructure before you take any externally-visible action. When you use `tofu taint`, other users could create a new plan against your tainted object before you can review the effects. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/taint/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------- Code Block $ tofu taint [options]
The `address` argument is the address of the resource to mark as tainted. The address is in [the resource address syntax](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/) , as shown in the output from other commands, such as: * `aws_instance.foo` * `aws_instance.bar[1]` * `aws_instance.baz[\"key\"]` (quotes in resource addresses must be escaped on the command line, so that they will not be interpreted by your shell) * `module.foo.module.bar.aws_instance.qux` Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu taint`. This command accepts the following options: * `-allow-missing` - If specified, the command will succeed (exit code 0) even if the resource is missing. The command might still return an error for other situations, such as if there is a problem reading or writing the state. * `-lock=false` - Disables OpenTofu's default behavior of attempting to take a read/write lock on the state for the duration of the operation. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.10/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.10/language/settings/backends/remote/) only, `tofu taint` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/v1.10/cli/cloud/command-line-arguments/#ignore-remote-version) . For configurations using [the `local` backend](https://opentofu.org/docs/v1.10/language/settings/backends/local/) only, `tofu taint` also accepts the legacy options [`-state`, `-state-out`, and `-backup`](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) . * [Recommended Alternative](https://opentofu.org/docs/v1.10/cli/commands/taint/#recommended-alternative) * [Usage](https://opentofu.org/docs/v1.10/cli/commands/taint/#usage) --- # Provider Mirrors in OCI Registries | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provider Mirrors in OCI Registries ================================== A "provider mirror" is a secondary location hosting a copy of a provider to be used instead of accessing the provider's primary OpenTofu Provider Registry. Creating a local mirror of some or all of the providers you use can reduce data transfer costs and can help with running OpenTofu in "air-gapped" environments that cannot access any services over the public internet. Alternative provider installation methods are configured as part of [the OpenTofu CLI Configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/) . You can configure installation from OCI Registries using an `oci_mirror` block as part of your [Explicit Installation Method Configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#explicit-installation-method-configuration) . Code Block provider_installation { oci_mirror { repository_template = "example.com/opentofu-providers/${namespace}/${type}" include = ["registry.opentofu.org/*/*"] }} The above example specifies that any provider that belongs to the primary OpenTofu Registry should instead be installed from a repository in an OCI registry, constructing the repository address dynamically using the components of the provider source address. For example, the provider source address `hashicorp/tls` is a shorthand for `registry.opentofu.org/hashicorp/tls`, and so it matches the installation method rule configured above, with `hashicorp` as the "namespace" and `tls` as the "type". Therefore this configuration calls for the provider to be installed from the repository named `opentofu-providers/hashicorp/tls` in the OCI registry running at `example.com`. `oci_mirror` installation method arguments[​](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#oci_mirror-installation-method-arguments "Direct link to oci_mirror-installation-method-arguments") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `repository_template`: A HCL-style template string that evaluates to an OCI repository address to use for a given provider. The following symbols are available for interpolation in the template: * `hostname`: The hostname of the primary registry that the provider belongs to, such as `registry.opentofu.org`. * `namespace`: The namespace that the provider belongs to within its origin registry, such as `hashicorp` in the above example. * `type`: The provider's "type" name, which is the final portion of the source address that's unique within a particular namespace, such as `tls` in the above example. The template **must** include an interpolation for any component of the provider source address that is not constrained exactly by the `include` argument. For example, setting `include = ["registry.opentofu.org/*/*"]` constrains to exactly one hostname but leaves the namespace and type wildcarded, and so the template must include an interpolation of each of `namespace` and `type`, but does not need to use `hostname`. * `include` and `exclude`: Lists of provider source address patterns that together specify what subset of providers are to be handled by this installation method, as described in [Explicit Installation Method Configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#explicit-installation-method-configuration) . Required OCI Repository Content[​](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#required-oci-repository-content "Direct link to Required OCI Repository Content") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The OCI repository selected by `repository_template` must contain content following a specific structure that allows OpenTofu to recognize the metadata for all of the available provider versions and their associated distribution packages. ### Tag Names[​](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#tag-names "Direct link to Tag Names") OpenTofu begins by listing all of the tags in the repository. A valid tag name must be a version number formatted using the syntax of [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html) , except that the tag name must use the underscore character (`_`) instead of the plus character (`+`) to delimit the optional "build metadata" portion. OpenTofu ignores all tags that cannot be parsed as version numbers, and then selects the greatest available version that matches all of the version constraints for this provider specified across all modules in the current OpenTofu configuration. ### Manifest Structure[​](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#manifest-structure "Direct link to Manifest Structure") OpenTofu providers use separate distribution packages for each supported operating system and CPU architecture, and so each tag in an OCI repository used as an OpenTofu provider mirror must refer to an [Image Index](https://github.com/opencontainers/image-spec/blob/v1.1.1/image-index.md) manifest that lists a separate manifest for each platform the provider has been compiled for. The index manifest **must** have its `artifactType` property set to `application/vnd.opentofu.provider` so that OpenTofu can recognize is as a representing a provider release. OpenTofu then searches the `manifests` array for a manifest descriptor whose `artifactType` is `application/vnd.opentofu.provider-target` and whose `platform` property matches the operating system and architecture that OpenTofu itself was compiled for. The selected descriptor is then used to retrieve an [Image Manifest](https://github.com/opencontainers/image-spec/blob/v1.1.1/manifest.md) representing the files and metadata needed to install the selected provider version for the current platform. This manifest must again have its `artifactType` set to `application/vnd.opentofu.provider-target`, to match the descriptor used to retrieve it. The image manifest's `layers` array must include exactly one descriptor whose `mediaType` is `archive/zip`, referring to a blob containing exactly the same `.zip` package that would be returned for the same version of the provider on the same platform if installed from the provider's origin registry. OpenTofu than finally retrieves the indicated blob and extracts the `.zip` archive into the provider cache directory so that it's available for use by subsequent workflow commands like [`tofu apply`](https://opentofu.org/docs/v1.10/cli/commands/apply/) . Assembling and Pushing Provider Manifests[​](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#assembling-and-pushing-provider-manifests "Direct link to Assembling and Pushing Provider Manifests") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Note This section currently describes a very manual process for constructing the required manifest structure as described in the previous section. The OpenTofu project is currently collaborating with the ORAS project to design and implement a more complete solution, which will be documented here once it's included in a generally-available ORAS release. ### Install and Configure ORAS[​](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#install-and-configure-oras "Direct link to Install and Configure ORAS") We recommend assembling and pushing the manifests and blobs for a provider using the CLI tool offered by [the ORAS project](https://oras.land/) . At the time of writing, multi-platform index support is not yet finalized in ORAS and so unfortunately the index manifest must be constructed manually. If you are installing and using ORAS for the first time, and you intend to push to an OCI registry that requires authentication, you will need to first obtain credentials for that repository using [`oras login`](https://oras.land/docs/commands/oras_login) . ### Local OCI Image Layout[​](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#local-oci-image-layout "Direct link to Local OCI Image Layout") The process of assembling OpenTofu provider manifests with ORAS requires multiple steps, and so we recommend pushing the various artifacts first to a local filesystem directory -- known as an [OCI Image Layout](https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md) -- and then pushing the resulting objects all at once to your target repository, to avoid making the intermediate steps visible to other users of the remote repository. The command line examples in the following sections use the ORAS option `--oci-layout` to specify that the target of each operation is a local filesystem directory called `tmp-layout`, in the current working directory. You can change the name `tmp-layout` to whatever path you wish, as long as you use a consistent pathname across all of the commands. ### Single-platform Image Manifests[​](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#single-platform-image-manifests "Direct link to Single-platform Image Manifests") The top-level index manifest will eventually refer to the manifests for each of the platform-specific artifacts, and so the platform-specific artifacts must be pushed first in order to construct their manifests and determine the digests used to refer to them. First you must obtain the official `.zip` distribution packages for the provider you are intending to re-publish. For providers in the official OpenTofu Registry you can find a link to the provider's GitHub repository and retrieve the `.zip` artifacts from one of its releases. For example, to prepare to re-package the `hashicorp/tls` provider: 1. Access [the `hashicorp/tls` provider's registry index page](https://search.opentofu.org/provider/hashicorp/tls/latest) . 2. Follow the "Repository" link in the navigation bar to [the provider's GitHub repository](https://github.com/opentofu/terraform-provider-tls) . 3. Find the "Releases" heading in the repository's own navigation bar and select the latest release, such which at the time of writing was [v4.0.6](https://github.com/opentofu/terraform-provider-tls/releases/tag/v4.0.6) . 4. Download the `.zip` assets for each platform you intend to include in your mirror into a new, empty directory on your local computer. After switching to that directory in your shell, you should be able to list all of the packages you downloaded: Code Block $ ls -1terraform-provider-tls_4.0.6_darwin_amd64.zipterraform-provider-tls_4.0.6_linux_386.zipterraform-provider-tls_4.0.6_linux_amd64.zipterraform-provider-tls_4.0.6_linux_arm.zipterraform-provider-tls_4.0.6_linux_arm64.zipterraform-provider-tls_4.0.6_windows_386.zipterraform-provider-tls_4.0.6_windows_amd64.zipterraform-provider-tls_4.0.6_windows_arm.zipterraform-provider-tls_4.0.6_windows_arm64.zip Use `oras push` for each package in turn to copy the `.zip` archive into your local OCI Image Layout and generate its manifest: Code Block $ oras push \ --artifact-type application/vnd.opentofu.provider-target \ --oci-layout tmp-layout:linux_amd64 \ terraform-provider-tls_4.0.6_linux_amd64.zip:archive/zipβœ“ Uploaded terraform-provider-tls_4.0.6_linux_amd64.zip └─ sha256:5f12d51fa9e87b6d29275fa58d1cd8681c0177a1d3a71a4e6c78ad7b011fa065βœ“ Uploaded application/vnd.oci.image.config.v1+json └─ sha256:9d99a75171aea000c711b34c0e5e3f28d3d537dd99d110eafbfbc2bd8e52c2bfβœ“ Uploaded application/vnd.oci.image.manifest.v1+json └─ sha256:01d3ccf9747dd604ebaa314efbacf12e18a248f8bf1c783f5cbb220754954e67Pushed [oci-layout] tmp-layout:linux_amd64ArtifactType: application/vnd.opentofu.provider-targetDigest: sha256:01d3ccf9747dd604ebaa314efbacf12e18a248f8bf1c783f5cbb220754954e67 The `Digest` returned at the end of the output is the identifier for the platform-specific manifest. The digest in the above example is a placeholder; your result will vary for each distinct provider package. Repeat the above command for each combination of operating system and CPU architecture that you want to include in your mirror distribution. Once you've pushed all of the packages you want to include, you can confirm all of the platform-specific tags you've created: Code Block $ oras repo tags --oci-layout tmp-layoutdarwin_amd64linux_386linux_amd64linux_armlinux_arm64windows_386windows_amd64windows_armwindows_arm64 ### Multi-platform Index Manifest[​](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#multi-platform-index-manifest "Direct link to Multi-platform Index Manifest") The current stable release of ORAS cannot construct and push an index manifest directly, but the "OCI Image Layout" that you constructed in the previous step includes its own index manifest that can be adapted to make it suitable for pushing to a remote repository. First, copy the Image Layout's index file to another file so that you can edit it without damaging the Image Layout directory: Code Block $ cp tmp-layout/index.json terraform-provider-tls_4.0.6.json Open the new `terraform-provider-tls_4.0.6.json` file in your favorite text editor. The JSON document is likely to be "minified", so you may wish to ask your text editor to reformat it for readability before continuing. The file should include a JSON property `"mediaType" : "application/vnd.oci.image.index.v1+json"` representing that this is an OCI Index Manifest. After that property, add a new JSON property `"artifactType":"application/vnd.opentofu.provider"` to represent that this is an index for an OpenTofu provider artifact. The file also includes a `"manifests"` property that describes each of the platform-specific manifests previously created. Each of these descriptor objects must contain a `"platform"` property specifying the platform that the manifest is for. For example: Code Block { "artifactType": "application/vnd.opentofu.provider-target", "mediaType": "application/vnd.oci.image.manifest.v1+json", "digest": "sha256:01d3ccf9747dd604ebaa314efbacf12e18a248f8bf1c783f5cbb220754954e67", "size": 606, "platform": { "os": "linux", "architecture": "amd64" }} Make sure that each of the manifest descriptors includes a `"platform"` property specifying the correct operating system and CPU architecture for the associated manifest. You can then push this new index manifest into the OCI layout, along with all of the single-platform artifacts pushed in the previous section: Code Block $ oras manifest push --oci-layout tmp-layout:4.0.6 terraform-provider-tls_4.0.6.json Uploading da13ebaa32ba application/vnd.oci.image.index.v1+jsonUploaded da13ebaa32ba application/vnd.oci.image.index.v1+jsonPushed: [oci-layout] tmp-layout:4.0.6Digest: sha256:da13ebaa32ba856d75da18e38daabc7a65ac8853230dfcc817f8ccbac15b639a Notice that the provider version 4.0.6 appears twice in this command line. The first is the name of the tag to create in the OCI layout, while the second is part of the filename of the index manifest saved in the previous step. The OCI Image Layout now contains individual tags for the platform-specific arfacts and also a version number tag representing the index manifest: Code Block $ oras repo tags --oci-layout tmp-layout4.0.6darwin_amd64linux_386linux_amd64linux_armlinux_arm64windows_386windows_amd64windows_armwindows_arm64 ### Push the Artifacts to a Remote Repository[​](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#push-the-artifacts-to-a-remote-repository "Direct link to Push the Artifacts to a Remote Repository") The local image layout now contains all of the information required to push this provider release to a remote repository. Code Block $ oras cp \ --from-oci-layout tmp-layout:4.0.6 \ example.com/opentofu-providers/hashicorp/tls:4.0.6βœ“ Copied terraform-provider-tls_4.0.6_linux_amd64.zip └─ sha256:5f12d51fa9e87b6d29275fa58d1cd8681c0177a1d3a71a4e6c78ad7b011fa065[...]βœ“ Copied application/vnd.oci.image.config.v1+json └─ sha256:9d99a75171aea000c711b34c0e5e3f28d3d537dd99d110eafbfbc2bd8e52c2bfβœ“ Copied application/vnd.oci.image.manifest.v1+json └─ sha256:01d3ccf9747dd604ebaa314efbacf12e18a248f8bf1c783f5cbb220754954e67βœ“ Copied application/vnd.oci.image.index.v1+json └─ sha256:da13ebaa32ba856d75da18e38daabc7a65ac8853230dfcc817f8ccbac15b639aCopied [oci-layout] tmp-layout:4.0.6 => [registry] example.com/opentofu-providers/hashicorp/tls:4.0.6Digest: sha256:da13ebaa32ba856d75da18e38daabc7a65ac8853230dfcc817f8ccbac15b639a ORAS copies everything that the local 4.0.6 tag refers to into the remote registry, and then creates a remote tag 4.0.6 referring to the same content. This provider is now available for use using an `oci_mirror` installation block configured as in the example at the start of this page. * [`oci_mirror` installation method arguments](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#oci_mirror-installation-method-arguments) * [Required OCI Repository Content](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#required-oci-repository-content) * [Tag Names](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#tag-names) * [Manifest Structure](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#manifest-structure) * [Assembling and Pushing Provider Manifests](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#assembling-and-pushing-provider-manifests) * [Install and Configure ORAS](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#install-and-configure-oras) * [Local OCI Image Layout](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#local-oci-image-layout) * [Single-platform Image Manifests](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#single-platform-image-manifests) * [Multi-platform Index Manifest](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#multi-platform-index-manifest) * [Push the Artifacts to a Remote Repository](https://opentofu.org/docs/v1.10/cli/oci_registries/provider-mirror/#push-the-artifacts-to-a-remote-repository) --- # Resource Graph | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/graph/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Resource Graph ============== OpenTofu builds a [dependency graph](https://en.wikipedia.org/wiki/Dependency_graph) from the OpenTofu configurations, and walks this graph to generate plans, refresh state, and more. This page documents the details of what are contained in this graph, what types of nodes there are, and how the edges of the graph are determined. Advanced Topic! This page covers technical details of OpenTofu. You don't need to understand these details to effectively use OpenTofu. The details are documented here for those who wish to learn about them without having to go spelunking through the source code. For some background on graph theory, and a summary of how OpenTofu applies it, see the HashiCorp 2016 presentation [_Applying Graph Theory to Infrastructure as Code_](https://www.youtube.com/watch?v=Ce3RNfRbdZ0) . This presentation also covers some similar ideas to the following guide. Graph Nodes[​](https://opentofu.org/docs/v1.10/internals/graph/#graph-nodes "Direct link to Graph Nodes") ---------------------------------------------------------------------------------------------------------- There are only a handful of node types that can exist within the graph. We'll cover these first before explaining how they're determined and built: * **Resource Node** - Represents a single resource. If you have the `count` metaparameter set, then there will be one resource node for each count. The configuration, diff, state, etc. of the resource under change is attached to this node. * **Provider Configuration Node** - Represents the time to fully configure a provider. This is when the provider configuration block is given to a provider, such as AWS security credentials. * **Resource Meta-Node** - Represents a group of resources, but does not represent any action on its own. This is done for convenience on dependencies and making a prettier graph. This node is only present for resources that have a `count` parameter greater than 1. When visualizing a configuration with `tofu graph`, you can see all of these nodes present. Building the Graph[​](https://opentofu.org/docs/v1.10/internals/graph/#building-the-graph "Direct link to Building the Graph") ------------------------------------------------------------------------------------------------------------------------------- Building the graph is done in a series of sequential steps: 1. Resources nodes are added based on the configuration. If a diff (plan) or state is present, that meta-data is attached to each resource node. 2. Resources are mapped to provisioners if they have any defined. This must be done after all resource nodes are created so resources with the same provisioner type can share the provisioner implementation. 3. Explicit dependencies from the `depends_on` meta-parameter are used to create edges between resources. 4. If a state is present, any "orphan" resources are added to the graph. Orphan resources are any resources that are no longer present in the configuration but are present in the state file. Orphans never have any configuration associated with them, since the state file does not store configuration. 5. Resources are mapped to providers. Provider configuration nodes are created for these providers, and edges are created such that the resources depend on their respective provider being configured. 6. Interpolations are parsed in resource and provider configurations to determine dependencies. References to resource attributes are turned into dependencies from the resource with the interpolation to the resource being referenced. 7. Create a root node. The root node points to all resources and is created so there is a single root to the dependency graph. When traversing the graph, the root node is ignored. 8. If a diff is present, traverse all resource nodes and find resources that are being destroyed. These resource nodes are split into two: one node that destroys the resource and another that creates the resource (if it is being recreated). The reason the nodes must be split is because the destroy order is often different from the create order, and so they can't be represented by a single graph node. 9. Validate the graph has no cycles and has a single root. Walking the Graph[​](https://opentofu.org/docs/v1.10/internals/graph/#walking-the-graph "Direct link to Walking the Graph") ---------------------------------------------------------------------------------------------------------------------------- To walk the graph, a standard depth-first traversal is done. Graph walking is done in parallel: a node is walked as soon as all of its dependencies are walked. The amount of parallelism is limited using a semaphore to prevent too many concurrent operations from overwhelming the resources of the machine running OpenTofu. By default, up to 10 nodes in the graph will be processed concurrently. This number can be set using the `-parallelism` flag on the [plan](https://opentofu.org/docs/v1.10/cli/commands/plan/) , [apply](https://opentofu.org/docs/v1.10/cli/commands/apply/) , and [destroy](https://opentofu.org/docs/v1.10/cli/commands/destroy/) commands. Setting `-parallelism` is considered an advanced operation and should not be necessary for normal usage of OpenTofu. It may be helpful in certain special use cases or to help debug OpenTofu issues. Note that some providers (AWS, for example), handle API rate limiting issues at a lower level by implementing graceful backoff/retry in their respective API clients. For this reason, OpenTofu does not use this `parallelism` feature to address API rate limits directly. * [Graph Nodes](https://opentofu.org/docs/v1.10/internals/graph/#graph-nodes) * [Building the Graph](https://opentofu.org/docs/v1.10/internals/graph/#building-the-graph) * [Walking the Graph](https://opentofu.org/docs/v1.10/internals/graph/#walking-the-graph) --- # Server-side Login Protocol | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/login-protocol/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Server-side Login Protocol ========================== Note You don't need to read these docs to _use_ [`tofu login`](https://opentofu.org/docs/v1.10/cli/commands/login/) . The information below is for anyone intending to implement the server side of `tofu login` in order to offer OpenTofu-native services in a third-party system. The `tofu login` command supports performing an OAuth 2.0 authorization request using configuration provided by the target host. You may wish to implement this protocol if you are producing a third-party implementation of any [OpenTofu-native services](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/) , such as an OpenTofu module registry. First, OpenTofu uses [remote service discovery](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/) to find the OAuth configuration for the host. The host must support the service name `login.v1` and define for it an object containing OAuth client configuration values, like this: Code Block { "login.v1": { "client": "tofu-cli", "grant_types": ["authz_code"], "authz": "/oauth/authorization", "token": "/oauth/token", "ports": [10000, 10010], }} The properties within the discovery object are as follows: * `client` (Required): The `client_id` value to use when making requests, as defined in [RFC 6749 section 2.2](https://tools.ietf.org/html/rfc6749#section-2.2) . Because OpenTofu is a _public client_ (it is installed on end-user systems and thus cannot protect an OAuth client secret), the `client_id` is purely advisory and the server must not use it as a guarantee that an authorization request is truly coming from OpenTofu. * `grant_types` (Optional): A JSON array of strings describing a set of OAuth 2.0 grant types the server is able to support. A "grant type" selects a specific mechanism by which an OAuth server authenticates the request and issues an authorization token. OpenTofu CLI supports a single grant type: * `authz_code`: [authorization code grant](https://tools.ietf.org/html/rfc6749#section-4.1) . Both the `authz` and `token` properties are required when `authz_code` is present. If not specified, `grant_types` defaults to `["authz_code"]`. * `authz` (Required if needed for a given grant type): the server's [authorization endpoint](https://tools.ietf.org/html/rfc6749#section-3.1) . If given as a relative URL, it is resolved from the location of the service discovery document. * `token` (Required if needed for a given grant type): the server's [token endpoint](https://tools.ietf.org/html/rfc6749#section-3.2) . If given as a relative URL, it is resolved from the location of the service discovery document. * `ports` (Optional): A two-element JSON array giving an inclusive range of TCP ports that OpenTofu may use for the temporary HTTP server it will start to provide the [redirection endpoint](https://tools.ietf.org/html/rfc6749#section-3.1.2) for the first step of an authorization code grant. OpenTofu opens a TCP listen port on the loopback interface in order to receive the response from the server's authorization endpoint. If not specified, OpenTofu is free to select any TCP port greater than or equal to 1024. OpenTofu allows constraining this port range for interoperability with OAuth server implementations that require each `client_id` to be associated with a fixed set of valid redirection endpoint URLs. Configure such a server to expect a range of URLs of the form `http://localhost:10000/` with different consecutive port numbers, and then specify that port range using `ports`. We recommend allowing at least 10 distinct port numbers if possible, and assigning them to numbers greater than or equal to 10000, to minimize the risk that all of the possible ports will already be in use on a particular system. When requesting an authorization code grant, OpenTofu CLI implements the [Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636) extension in order to protect against other applications on the system intercepting the incoming request to the redirection endpoint. We strongly recommend that you select an OAuth server implementation that also implements this extension and verifies the code challenge sent to the token endpoint. OpenTofu CLI does not support OAuth refresh tokens or token expiration. If your server issues time-limited tokens, OpenTofu CLI will simply begin receiving authorization errors once the token expires, after which the user can run `tofu login` again to obtain a new token. --- # Functions Metadata | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/functions-meta/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Functions Metadata ================== The `tofu metadata functions` command is used to print signatures for the functions available in the current OpenTofu version. Usage[​](https://opentofu.org/docs/v1.10/internals/functions-meta/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------- Usage: `tofu metadata functions [options]` The following flags are available: * `-json` - Displays the function signatures in a machine-readable, JSON format. Please note that, at this time, the `-json` flag is a _required_ option. In future releases, this command will be extended to allow for additional options. The output includes a `format_version` key, which has value `"1.0"`. The semantics of this version are: * We will increment the minor version, e.g. `"1.1"`, for backward-compatible changes or additions. Ignore any object properties with unrecognized names to remain forward-compatible with future minor versions. * We will increment the major version, e.g. `"2.0"`, for changes that are not backward-compatible. Reject any input which reports an unsupported major version. We will introduce new major versions only within the bounds of [the OpenTofu 1.0 Compatibility Promises](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/) . Format Summary[​](https://opentofu.org/docs/v1.10/internals/functions-meta/#format-summary "Direct link to Format Summary") ---------------------------------------------------------------------------------------------------------------------------- The following sections describe the JSON output format by example, using a pseudo-JSON notation. Important elements are described with comments, which are prefixed with `//`. To avoid excessive repetition, we've split the complete format into several discrete sub-objects, described under separate headers. References wrapped in angle brackets (like ``) are placeholders which, in the real output, would be replaced by an instance of the specified sub-object. The JSON output format consists of the following objects and sub-objects: * [Function Signature Representation](https://opentofu.org/docs/v1.10/internals/functions-meta/#function-signature-representation) - the top-level object returned by `tofu metadata functions -json` * [Parameter Representation](https://opentofu.org/docs/v1.10/internals/functions-meta/#parameter-representation) - a sub-object of signatures that describes their parameters Function Signature Representation[​](https://opentofu.org/docs/v1.10/internals/functions-meta/#function-signature-representation "Direct link to Function Signature Representation") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block { "format_version": "1.0", // "function_signatures" describes the signatures for all // available functions. "function_signatures": { // keys in this map are the function names, such as "abs" "example_function": { // "description" is an English-language description of // the purpose and usage of the function in Markdown. "description": "string", // "return_type" is a representation of a type specification // that the function returns. "return_type": "string", // "parameters" is an optional list of the positional parameters // that the function accepts. "parameters": [ , … ], // "variadic_parameter" is an optional representation of the // additional arguments that the function accepts after those // matching with the fixed parameters. "variadic_parameter": }, "example_function_two": { … } }} Parameter Representation[​](https://opentofu.org/docs/v1.10/internals/functions-meta/#parameter-representation "Direct link to Parameter Representation") ---------------------------------------------------------------------------------------------------------------------------------------------------------- A parameter representation describes a parameter to a function. Code Block { // "name" is the internal name of the parameter "name": "string", // "description" is an optional English-language description of // the purpose and usage of the parameter in Markdown. "description": "string", // "type" is a representation of a type specification // that the parameter's value must conform to. "type": "string"} * [Usage](https://opentofu.org/docs/v1.10/internals/functions-meta/#usage) * [Format Summary](https://opentofu.org/docs/v1.10/internals/functions-meta/#format-summary) * [Function Signature Representation](https://opentofu.org/docs/v1.10/internals/functions-meta/#function-signature-representation) * [Parameter Representation](https://opentofu.org/docs/v1.10/internals/functions-meta/#parameter-representation) --- # Command: workspace | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/workspace/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: workspace ================== The `tofu workspace` command is used to manage [workspaces](https://opentofu.org/docs/v1.10/language/state/workspaces/) . This command is a container for further subcommands that each have their own page in the documentation. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/workspace/#usage "Direct link to Usage") ----------------------------------------------------------------------------------------------- Usage: `tofu workspace [options] [args]` Choose a subcommand page for more information. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/workspace/#usage) --- # Managing Workspaces | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/workspaces/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Managing Workspaces =================== Workspaces in the OpenTofu CLI refer to separate instances of [state data](https://opentofu.org/docs/v1.10/language/state/) inside the same OpenTofu working directory. They are distinctly different from workspaces in a cloud backend, which each have their own OpenTofu configuration and function as separate working directories. OpenTofu relies on state to associate resources with real-world objects. When you run the same configuration multiple times with separate state data, OpenTofu can manage multiple sets of non-overlapping resources. Workspaces can be helpful for specific [use cases](https://opentofu.org/docs/v1.10/cli/workspaces/#use-cases) , but they are not required to use the OpenTofu CLI. We recommend using [alternative approaches](https://opentofu.org/docs/v1.10/cli/workspaces/#alternatives-to-workspaces) for complex deployments requiring separate credentials and access controls. Managing CLI Workspaces[​](https://opentofu.org/docs/v1.10/cli/workspaces/#managing-cli-workspaces "Direct link to Managing CLI Workspaces") --------------------------------------------------------------------------------------------------------------------------------------------- Every [initialized working directory](https://opentofu.org/docs/v1.10/cli/init/) starts with one workspace named `default`. Use the [`tofu workspace list`](https://opentofu.org/docs/v1.10/cli/commands/workspace/list/) , [`tofu workspace new`](https://opentofu.org/docs/v1.10/cli/commands/workspace/new/) , and [`tofu workspace delete`](https://opentofu.org/docs/v1.10/cli/commands/workspace/delete/) commands to manage the available workspaces in the current working directory. Use [the `tofu workspace select` command](https://opentofu.org/docs/v1.10/cli/commands/workspace/select/) to change the currently selected workspace. For a given working directory, you can only select one workspace at a time. Most OpenTofu commands only interact with the currently selected workspace. This includes [provisioning](https://opentofu.org/docs/v1.10/cli/run/) and [state manipulation](https://opentofu.org/docs/v1.10/cli/state/) . When you provision infrastructure in each workspace, you usually need to manually specify different [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) to differentiate each collection. For example, you might deploy test infrastructure to a different region. Use Cases[​](https://opentofu.org/docs/v1.10/cli/workspaces/#use-cases "Direct link to Use Cases") --------------------------------------------------------------------------------------------------- You can create multiple [working directories](https://opentofu.org/docs/v1.10/cli/init/) to maintain multiple instances of a configuration with completely separate state data. However, OpenTofu installs a separate cache of plugins and modules for each working directory, so maintaining multiple directories can waste bandwidth and disk space. This approach also requires extra tasks like updating configuration from version control for each directory separately and reinitializing each directory when you change the configuration. Workspaces are convenient because they let you create different sets of infrastructure with the same working copy of your configuration and the same plugin and module caches. A common use for multiple workspaces is to create a parallel, distinct copy of a set of infrastructure to test a set of changes before modifying production infrastructure. Non-default workspaces are often related to feature branches in version control. The default workspace might correspond to the `main` or `trunk` branch, which describes the intended state of production infrastructure. When a developer creates a feature branch for a change, they might also create a corresponding workspace and deploy into it a temporary copy of the main infrastructure. They can then test changes on the copy without affecting the production infrastructure. Once the change is merged and deployed to the default workspace, they destroy the test infrastructure and delete the temporary workspace. ### When Not to Use Multiple Workspaces[​](https://opentofu.org/docs/v1.10/cli/workspaces/#when-not-to-use-multiple-workspaces "Direct link to When Not to Use Multiple Workspaces") Workspaces let you quickly switch between multiple instances of a **single configuration** within its **single backend**. They are not designed to solve all problems. When using OpenTofu to manage larger systems, you should create separate OpenTofu configurations that correspond to architectural boundaries within the system. This lets teams manage different components separately. Workspaces alone are not a suitable tool for system decomposition because each subsystem should have its own separate configuration and backend. In particular, organizations commonly want to create a strong separation between multiple deployments of the same infrastructure serving different development stages or different internal teams. In this case, the backend for each deployment often has different credentials and access controls. CLI workspaces within a working directory use the same backend, so they are not a suitable isolation mechanism for this scenario. Alternatives to Workspaces[​](https://opentofu.org/docs/v1.10/cli/workspaces/#alternatives-to-workspaces "Direct link to Alternatives to Workspaces") ------------------------------------------------------------------------------------------------------------------------------------------------------ Instead of creating CLI workspaces, you can use one or more [re-usable modules](https://opentofu.org/docs/v1.10/language/modules/develop/) to represent the common elements and then represent each instance as a separate configuration that instantiates those common elements in the context of a different [backend](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) . The root module of each configuration consists only of a backend configuration and a small number of `module` blocks with arguments describing any small differences between the deployments. When multiple configurations represent distinct system components rather than multiple deployments, you can pass data from one component to another using paired resources types and data sources. * If you have a configuration management system accessible from all configurations, then one can use a `resource` to export variables, while another configuration can use a `datasource` to import them. * In systems that support user-defined labels or tags, use a tagging convention to make resources automatically discoverable. For example, use [the `aws_vpc` resource type](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc) to assign suitable tags and then [the `aws_vpc` data source](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) to query by those tags in other configurations. * For server addresses, use a provider-specific resource to create a DNS record with a predictable name. Then you can either use that name directly or use [the `dns` provider](https://registry.terraform.io/providers/hashicorp/dns/latest/docs) to retrieve the published addresses in other configurations. * If you store a OpenTofu state for one configuration in a remote backend that other configurations can access, then the other configurations can use [`terraform_remote_state`](https://opentofu.org/docs/v1.10/language/state/remote-state-data/) to directly consume its root module outputs. This setup creates a tighter coupling between configurations, and the root configuration does not need to publish its results in a separate system. Workspace Internals[​](https://opentofu.org/docs/v1.10/cli/workspaces/#workspace-internals "Direct link to Workspace Internals") --------------------------------------------------------------------------------------------------------------------------------- Workspaces are technically equivalent to renaming your state file. OpenTofu then includes a set of protections and support for remote state. Workspaces are also meant to be a shared resource. They are not private, unless you use purely local state and do not commit your state to version control. For local state, OpenTofu stores the workspace states in a directory called `terraform.tfstate.d`. This directory should be treated similarly to local-only `terraform.tfstate`. Some teams commit these files to version control, but we recommend using a remote backend instead when there are multiple collaborators. For [remote state](https://opentofu.org/docs/v1.10/language/state/remote/) , the workspaces are stored directly in the configured [backend](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) . For example, if you use [Consul](https://opentofu.org/docs/v1.10/language/settings/backends/consul/) , the workspaces are stored by appending the workspace name to the state path. To ensure that workspace names are stored correctly and safely in all backends, the name must be valid to use in a URL path segment without escaping. OpenTofu stores the current workspace name locally in the ignored `.terraform` directory. This allows multiple team members to work on different workspaces concurrently. Workspace names are also attached to associated remote workspaces in a cloud backend. For more details about workspace names in cloud backends, refer to the [CLI Integration (recommended)](https://opentofu.org/docs/v1.10/cli/cloud/settings/#arguments) and [remote backend](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#workspaces) and documentation. * [Managing CLI Workspaces](https://opentofu.org/docs/v1.10/cli/workspaces/#managing-cli-workspaces) * [Use Cases](https://opentofu.org/docs/v1.10/cli/workspaces/#use-cases) * [When Not to Use Multiple Workspaces](https://opentofu.org/docs/v1.10/cli/workspaces/#when-not-to-use-multiple-workspaces) * [Alternatives to Workspaces](https://opentofu.org/docs/v1.10/cli/workspaces/#alternatives-to-workspaces) * [Workspace Internals](https://opentofu.org/docs/v1.10/cli/workspaces/#workspace-internals) --- # Provider Metadata | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/provider-meta/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provider Metadata ================= In some situations it's beneficial for a provider to offer an interface through which modules can pass it information unrelated to the resources in the module, but scoped on a per-module basis. Provider Metadata allows a provider to declare metadata fields it expects, which individual modules can then populate independently of any provider configuration. While provider configurations are often shared between modules, provider metadata is always module-specific. Provider Metadata is intended primarily for the situation where an official module is developed by the same vendor that produced the provider it is intended to work with, to allow the vendor to indirectly obtain usage statistics for each module via the provider. For that reason, this documentation is presented from the perspective of the provider developer rather than the module developer. Advanced Topic! This page covers technical details of OpenTofu. You don't need to understand these details to effectively use OpenTofu. The details are documented here for module authors and provider developers working on advanced functionality. Experimental Feature! This functionality is still considered experimental, and anyone taking advantage of it should [coordinate with the OpenTofu team](https://github.com/opentofu/opentofu/issues/new) to help the team understand how the feature is being used and to make sure their use case is taken into account as the feature develops. Defining the Schema[​](https://opentofu.org/docs/v1.10/internals/provider-meta/#defining-the-schema "Direct link to Defining the Schema") ------------------------------------------------------------------------------------------------------------------------------------------ Before a provider can receive information from a module, the provider must strictly define the data it can accept. You can do this by setting the `ProviderMeta` property on your `schema.Provider` struct. Its value functions similarly to the provider config: a map of strings to the `schema.Schema` describing the values those strings accept. Using the Data[​](https://opentofu.org/docs/v1.10/internals/provider-meta/#using-the-data "Direct link to Using the Data") --------------------------------------------------------------------------------------------------------------------------- When OpenTofu calls your provider, you can use the `schema.ResourceData` that your `Create`, `Read`, and `Update` functions already use to get access to the provider metadata being passed. First define a struct that matches your schema, then call the `GetProviderSchema` method on your `schema.ResourceData`, passing a pointer to a variable of that type. The variable will be populated with the provider metadata, and will return an error if there was an issue with parsing the data into the struct. Specifying Data in Modules[​](https://opentofu.org/docs/v1.10/internals/provider-meta/#specifying-data-in-modules "Direct link to Specifying Data in Modules") --------------------------------------------------------------------------------------------------------------------------------------------------------------- To include data in your modules, create a `provider_meta` nested block under your module's `terraform` block, with the name of the provider it's trying to pass information to: Code Block terraform { provider_meta "my-provider" { hello = "world" }} The `provider_meta` block must match the schema the provider has defined. Versioning Your Modules[​](https://opentofu.org/docs/v1.10/internals/provider-meta/#versioning-your-modules "Direct link to Versioning Your Modules") ------------------------------------------------------------------------------------------------------------------------------------------------------ Any module taking advantage of this functionality must make sure that the provider metadata supplied matches the schema defined in the provider, and that the version of OpenTofu that is being run has support for the provider metadata functionality. It's therefore recommended that any module taking advantage of this functionality should specify a minimum OpenTofu version of 0.13.0 or higher, and a minimum version of each of the providers it specifies metadata as the first version the schema being used was supported by the provider. * [Defining the Schema](https://opentofu.org/docs/v1.10/internals/provider-meta/#defining-the-schema) * [Using the Data](https://opentofu.org/docs/v1.10/internals/provider-meta/#using-the-data) * [Specifying Data in Modules](https://opentofu.org/docs/v1.10/internals/provider-meta/#specifying-data-in-modules) * [Versioning Your Modules](https://opentofu.org/docs/v1.10/internals/provider-meta/#versioning-your-modules) --- # Getting started | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page What is OpenTofu? ================= OpenTofu is an infrastructure as code tool that lets you define both cloud and on-prem resources in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to provision and manage all of your infrastructure throughout its lifecycle. OpenTofu can manage low-level components like compute, storage, and networking resources, as well as high-level components like DNS entries and SaaS features. How does OpenTofu work?[​](https://opentofu.org/docs/v1.10/intro/#how-does-opentofu-work "Direct link to How does OpenTofu work?") ----------------------------------------------------------------------------------------------------------------------------------- OpenTofu creates and manages resources on cloud platforms and other services through their application programming interfaces (APIs). Providers enable OpenTofu to work with virtually any platform or service with an accessible API. The OpenTofu community have already written **thousands of providers** to manage many different types of resources and services. You can find all publicly available providers on the [Public OpenTofu Registry](https://github.com/opentofu/registry/tree/main/providers) , including Amazon Web Services (AWS), Azure, Google Cloud Platform (GCP), Kubernetes, Helm, GitHub, Splunk, DataDog, and many more. The core OpenTofu workflow consists of three stages: * **Write:** You define resources, which may be across multiple cloud providers and services. For example, you might create a configuration to deploy an application on virtual machines in a Virtual Private Cloud (VPC) network with security groups and a load balancer. * **Plan:** OpenTofu creates an execution plan describing the infrastructure it will create, update, or destroy based on the existing infrastructure and your configuration. * **Apply:** On approval, OpenTofu performs the proposed operations in the correct order, respecting any resource dependencies. For example, if you update the properties of a VPC and change the number of virtual machines in that VPC, OpenTofu will recreate the VPC before scaling the virtual machines. Why OpenTofu?[​](https://opentofu.org/docs/v1.10/intro/#why-opentofu "Direct link to Why OpenTofu?") ----------------------------------------------------------------------------------------------------- ### Manage any infrastructure[​](https://opentofu.org/docs/v1.10/intro/#manage-any-infrastructure "Direct link to Manage any infrastructure") Find providers for many of the platforms and services you already use in the [Public OpenTofu Registry](https://registry.opentofu.org/) . You can also use the [Terraform Plugin SDK](https://developer.hashicorp.com/terraform/plugin) to write your own. OpenTofu takes an [immutable approach to infrastructure](https://www.hashicorp.com/resources/what-is-mutable-vs-immutable-infrastructure) , reducing the complexity of upgrading or modifying your services and infrastructure. ### Track your infrastructure[​](https://opentofu.org/docs/v1.10/intro/#track-your-infrastructure "Direct link to Track your infrastructure") OpenTofu generates a plan and prompts you for your approval before modifying your infrastructure. It also keeps track of your real infrastructure in a [state file](https://opentofu.org/docs/v1.10/language/state/) , which acts as a source of truth for your environment. OpenTofu uses the state file to determine the changes to make to your infrastructure so that it will match your configuration. ### Automate changes[​](https://opentofu.org/docs/v1.10/intro/#automate-changes "Direct link to Automate changes") OpenTofu configuration files are declarative, meaning that they describe the end state of your infrastructure. You do not need to write step-by-step instructions to create resources because OpenTofu handles the underlying logic. OpenTofu builds a resource graph to determine resource dependencies and creates or modifies non-dependent resources in parallel. This allows OpenTofu to provision resources efficiently. ### Standardize configurations[​](https://opentofu.org/docs/v1.10/intro/#standardize-configurations "Direct link to Standardize configurations") OpenTofu supports reusable configuration components called [modules](https://opentofu.org/docs/v1.10/language/modules/) that define configurable collections of infrastructure, saving time and encouraging best practices. You can use publicly available modules from the OpenTofu Registry, or write your own. ### Collaborate[​](https://opentofu.org/docs/v1.10/intro/#collaborate "Direct link to Collaborate") Since your configuration is written in a file, you can commit it to a Version Control System (VCS) and use a cloud backend to efficiently manage OpenTofu workflows across teams. A cloud backend runs OpenTofu in a consistent, reliable environment and provides secure access to shared state and secret data, role-based access controls, a private registry for sharing both modules and providers, and more. Tip Learn more about [OpenTofu use cases](https://opentofu.org/docs/v1.10/intro/use-cases/) and [how OpenTofu compares to alternatives](https://opentofu.org/docs/v1.10/intro/vs/) . Community[​](https://opentofu.org/docs/v1.10/intro/#community "Direct link to Community") ------------------------------------------------------------------------------------------ We welcome questions, suggestions, and contributions from the community. * Ask questions in [OpenTofu Discuss](https://github.com/orgs/opentofu/discussions) . * Read our [contributing guide](https://github.com/opentofu/opentofu/blob/main/CONTRIBUTING.md) . * [Submit an issue](https://github.com/opentofu/opentofu/issues) for bugs and feature requests. * [How does OpenTofu work?](https://opentofu.org/docs/v1.10/intro/#how-does-opentofu-work) * [Why OpenTofu?](https://opentofu.org/docs/v1.10/intro/#why-opentofu) * [Manage any infrastructure](https://opentofu.org/docs/v1.10/intro/#manage-any-infrastructure) * [Track your infrastructure](https://opentofu.org/docs/v1.10/intro/#track-your-infrastructure) * [Automate changes](https://opentofu.org/docs/v1.10/intro/#automate-changes) * [Standardize configurations](https://opentofu.org/docs/v1.10/intro/#standardize-configurations) * [Collaborate](https://opentofu.org/docs/v1.10/intro/#collaborate) * [Community](https://opentofu.org/docs/v1.10/intro/#community) --- # Forcing Re-creation of Resources | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/state/taint/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Forcing Re-creation of Resources ================================ During planning, by default OpenTofu retrieves the latest state of each existing object and compares it with the current configuration, planning actions only against objects whose current state does not match the configuration. However, in some cases a remote object may become damaged or degraded in a way that OpenTofu cannot automatically detect. For example, if software running inside a virtual machine crashes but the virtual machine itself is still running then OpenTofu will typically have no way to detect and respond to the problem, because OpenTofu only directly manages the machine as a whole. If you know that an object is damaged, or if you want to force OpenTofu to replace it for any other reason, you can override OpenTofu's default behavior using [the `-replace=...` planning option](https://opentofu.org/docs/v1.10/cli/commands/plan/#replace-address) when you run either `tofu plan` or `tofu apply`: Code Block $ tofu apply -replace="aws_instance.example"# ... # aws_instance.example will be replaced, as requested-/+ resource "aws_instance" "example" { # ... } The "tainted" status[​](https://opentofu.org/docs/v1.10/cli/state/taint/#the-tainted-status "Direct link to The "tainted" status") ----------------------------------------------------------------------------------------------------------------------------------- Sometimes OpenTofu is able to infer automatically that an object is in an incomplete or degraded state. For example, if creation of a complex object fails in such a way that parts of it already exist in the remote system, or if object creation succeeded but a provisioner step subsequently failed, OpenTofu must remember that the object exists but may not be fully-functional. OpenTofu represents this situation by marking an object in the state as "tainted". When an object is marked with this status, the next plan will force replacing that object in a similar way to if you had specified that object's address using `-replace=...` as described above. Code Block # aws_instance.example is tainted, so it must be replaced-/+ resource "aws_instance" "example" { # ... } If OpenTofu has marked an object as tainted but you consider it to be working correctly and do not want to replace it, you can override OpenTofu's determination using [the `tofu untaint` command](https://opentofu.org/docs/v1.10/cli/commands/untaint/) , after which OpenTofu will consider the object to be ready for use by any downstream resource declarations. You can also _force_ OpenTofu to mark a particular object as tainted using [the `tofu taint` command](https://opentofu.org/docs/v1.10/cli/commands/taint/) , but that approach is deprecated in favor of the `-replace=...` option, which avoids the need to create an interim state snapshot with a tainted object. * [The "tainted" status](https://opentofu.org/docs/v1.10/cli/state/taint/#the-tainted-status) --- # Command: workspace show | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/workspace/show/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: workspace show ======================= The `tofu workspace show` command is used to output the current workspace. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/workspace/show/#usage "Direct link to Usage") ---------------------------------------------------------------------------------------------------- Usage: `tofu workspace show` The command will display the current workspace. Example[​](https://opentofu.org/docs/v1.10/cli/commands/workspace/show/#example "Direct link to Example") ---------------------------------------------------------------------------------------------------------- Code Block $ tofu workspace showdevelopment * [Usage](https://opentofu.org/docs/v1.10/cli/commands/workspace/show/#usage) * [Example](https://opentofu.org/docs/v1.10/cli/commands/workspace/show/#example) --- # Resource Addressing | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Resource Addressing =================== A _resource address_ is a string that identifies zero or more resource instances in your overall configuration. An address is made up of two parts: Code Block [module path][resource spec] In some contexts OpenTofu might allow for an incomplete resource address that only refers to a module as a whole, or that omits the index for a multi-instance resource. In those cases, the meaning depends on the context, so you'll need to refer to the documentation for the specific feature you are using which parses resource addresses. Module path[​](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#module-path "Direct link to Module path") ------------------------------------------------------------------------------------------------------------------------ A module path addresses a module within the tree of modules. It takes the form: Code Block module.module_name[module index] * `module` - Module keyword indicating a child module (non-root). Multiple `module` keywords in a path indicate nesting. * `module_name` - User-defined name of the module. * `[module index]` - (Optional) [Index](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#index-values-for-modules-and-resources) to select an instance from a module call that has multiple instances, surrounded by square bracket characters (`[` and `]`). An address without a resource spec, i.e. `module.foo` applies to every resource within the module if a single module, or all instances of a module if a module has multiple instances. To address all resources of a particular module instance, include the module index in the address, such as `module.foo[0]`. If the module path is omitted, the address applies to the root module. An example of the `module` keyword delineating between two modules that have multiple instances: Code Block module.foo[0].module.bar["a"] Resource spec[​](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#resource-spec "Direct link to Resource spec") ------------------------------------------------------------------------------------------------------------------------------ A resource spec addresses a specific resource instance in the selected module. It has the following syntax: Code Block resource_type.resource_name[instance index] * `resource_type` - Type of the resource being addressed. * `resource_name` - User-defined name of the resource. * `[instance index]` - (Optional) [Index](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#index-values-for-modules-and-resources) to select an instance from a resource that has multiple instances, surrounded by square bracket characters (`[` and `]`). A resource spec without a module path prefix matches only resources in the root module. Index values for Modules and Resources[​](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#index-values-for-modules-and-resources "Direct link to Index values for Modules and Resources") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The following specifications apply to index values on modules and resources with multiple instances: * `[N]` where `N` is a `0`\-based numerical index into a resource with multiple instances specified by the `count` meta-argument. Omitting an index when addressing a resource where `count > 1` means that the address references all instances. * `["INDEX"]` where `INDEX` is a alphanumerical key index into a resource with multiple instances specified by the `for_each` meta-argument. Examples[​](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#examples "Direct link to Examples") --------------------------------------------------------------------------------------------------------------- ### count Example[​](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#count-example "Direct link to count Example") Given a OpenTofu config that includes: Code Block resource "aws_instance" "web" { # ... count = 4} An address like this: Code Block aws_instance.web[3] Refers to only the last instance in the config, and an address like this: Code Block aws_instance.web Refers to all four "web" instances. ### for\_each Example[​](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#for_each-example "Direct link to for_each Example") Given a OpenTofu config that includes: Code Block resource "aws_instance" "web" { # ... for_each = { "tofu": "value1", "resource": "value2", "indexing": "value3", "example": "value4", }} An address like this: Code Block aws_instance.web["example"] Refers to only the "example" instance in the config, and resolves to "value4". Resource Addresses on the Command Line[​](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#resource-addresses-on-the-command-line "Direct link to Resource Addresses on the Command Line") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When using resource addresses directly in command line arguments such as the `-target`, `-exclude`, and `-replace` planning options, the punctuation characters in the resource address syntax might conflict with special interpretation of those characters by the shell you are using to run OpenTofu. To avoid this, you must ensure that those characters are properly quoted or escaped so that your shell will pass them literally to OpenTofu. The syntax for doing so varies depending on your shell or command interpreter: * For Unix-style shells such as `bash`, write the resource address in single quotes (`'`): Code Block tofu apply -target='aws_instance.example["foo"]' If you need to specify an instance key string that includes a single quote character, use two separate single-quoted sequences with an escaped single quote between them. For example, the following includes the instance key `"example'foo"`: Code Block tofu apply -target='aws_instance.example["example'\''foo"]' * For PowerShell 7.3 or later, write the resource address in single quotes (`'`): Code Block tofu apply -target='aws_instance.example["foo"]' Older versions of PowerShell have different requirements. For more information, refer to [Passing arguments that contain quote characters](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing?view=powershell-7.5#passing-arguments-that-contain-quote-characters) . If you need to specify an instance key string that includes a single quote character, use two consecutive single quotes to represent a single literal quote. For example, the following includes the instance key `"example'foo"`: Code Block tofu apply -target='aws_instance.example["example''foo"]' * For Windows Command Prompt (`cmd.exe`), write the resource address in double quotes (`"`) and escape any quotes from the resource address using a backslash (`\`): Code Block tofu apply -target="aws_instance.example[\"foo\"]" Resource Addresses in Targeting Files[​](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#resource-addresses-in-targeting-files "Direct link to Resource Addresses in Targeting Files") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ The `-target-file` and `-exclude-file` [planning options](https://opentofu.org/docs/v1.10/cli/commands/plan/#planning-options) read resource addresses from a separate file that can contain zero or more resource addresses. OpenTofu interprets a targeting file on a line-by-line basis. The content of each line must be one of the following: * A resource address using the syntax described above, in which case OpenTofu adds the address to the set of target addresses. * A comment starting with the `#` character, in which case OpenTofu ignores the line completely. * A blank line consisting only of zero or more space characters, in which case OpenTofu also ignores the line completely. For example, the following is a valid targeting file specifying a number of resource addresses that might need to be created first when applying a certain configuration for the first time: Code Block # These modules must be targeted during initial creation.module.networkmodule.cluster# The following resources must also be included on initial# creation.aws_iam_role.all["base"]aws_iam_role_policy.all["base"] The targeting file above would match all instances of all resources whose addresses begin with `module.network` or `module.cluster`, and also the specific resource instances `aws_iam_role.all["base"]` and `aws_iam_role_policy.all["base"]`. * [Module path](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#module-path) * [Resource spec](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#resource-spec) * [Index values for Modules and Resources](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#index-values-for-modules-and-resources) * [Examples](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#examples) * [count Example](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#count-example) * [for\_each Example](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#for_each-example) * [Resource Addresses on the Command Line](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#resource-addresses-on-the-command-line) * [Resource Addresses in Targeting Files](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/#resource-addresses-in-targeting-files) --- # Working with OpenTofu | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/core-workflow/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Working with OpenTofu ===================== The core OpenTofu workflow has three steps: 1. **Write** - Author infrastructure as code. 2. **Plan** - Preview changes before applying. 3. **Apply** - Provision reproducible infrastructure. This guide walks through how each of these three steps plays out in the context of working as an individual practitioner, how they evolve when a team is collaborating on infrastructure, and how a cloud backend enables this workflow to run smoothly for entire organizations. Working as an Individual Practitioner[​](https://opentofu.org/docs/v1.10/intro/core-workflow/#working-as-an-individual-practitioner "Direct link to Working as an Individual Practitioner") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Let's first walk through how these parts fit together as an individual working on infrastructure as code. ### Write[​](https://opentofu.org/docs/v1.10/intro/core-workflow/#write "Direct link to Write") You write OpenTofu configuration just like you write code: in your editor of choice. It's common practice to store your work in a version controlled repository even when you're just operating as an individual. Code Block # Create repository$ git init my-infra && cd my-infraInitialized empty Git repository in /.../my-infra/.git/# Write initial config$ vim main.tf# Initialize OpenTofu$ tofu initInitializing provider plugins...# ...OpenTofu has been successfully initialized! As you make progress on authoring your config, repeatedly running plans can help flush out syntax errors and ensure that your config is coming together as you expect. Code Block # Make edits to config$ vim main.tf# Review plan$ tofu plan# Make additional edits, and repeat$ vim main.tf This parallels working on application code as an individual, where a tight feedback loop between editing code and running test commands is useful. ### Plan[​](https://opentofu.org/docs/v1.10/intro/core-workflow/#plan "Direct link to Plan") When the feedback loop of the Write step has yielded a change that looks good, it's time to commit your work and review the final plan. Code Block $ git add main.tf$ git commit -m 'Managing infrastructure as code!'[main (root-commit) f735520] Managing infrastructure as code! 1 file changed, 1 insertion(+) Because `tofu apply` will display a plan for confirmation before proceeding to change any infrastructure, that's the command you run for final review. Code Block $ tofu applyAn execution plan has been generated and is shown below.# ... ### Apply[​](https://opentofu.org/docs/v1.10/intro/core-workflow/#apply "Direct link to Apply") After one last check, you are ready to tell OpenTofu to provision real infrastructure. Code Block Do you want to perform these actions? OpenTofu will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes# ...Apply complete! Resources: 1 added, 0 changed, 0 destroyed. At this point, it's common to push your version control repository to a remote location for safekeeping. Code Block $ git remote add origin https://github.com/*user*/*repo*.git$ git push origin main This core workflow is a loop; the next time you want to make changes, you start the process over from the beginning. Notice how closely this workflow parallels the process of writing application code or scripts as an individual? This is what we mean when we talk about OpenTofu enabling infrastructure as code. Working as a Team[​](https://opentofu.org/docs/v1.10/intro/core-workflow/#working-as-a-team "Direct link to Working as a Team") -------------------------------------------------------------------------------------------------------------------------------- Once multiple people are collaborating on OpenTofu configuration, new steps must be added to each part of the core workflow to ensure everyone is working together smoothly. You'll see that many of these steps parallel the workflow changes we make when we work on application code as teams rather than as individuals. ### Write[​](https://opentofu.org/docs/v1.10/intro/core-workflow/#write-1 "Direct link to Write") While each individual on a team still makes changes to OpenTofu configuration in their editor of choice, they save their changes to version control _branches_ to avoid colliding with each other's work. Working in branches enables team members to resolve mutually incompatible infrastructure changes using their normal merge conflict workflow. Code Block $ git checkout -b add-load-balancerSwitched to a new branch 'add-load-balancer' Running iterative plans is still useful as a feedback loop while authoring configuration, though having each team member's computer able to run them becomes more difficult with time. As the team and the infrastructure grows, so does the number of sensitive input variables (e.g. API Keys, SSL Cert Pairs) required to run a plan. To avoid the burden and the security risk of each team member arranging all sensitive inputs locally, it's common for teams to migrate to a model in which OpenTofu operations are executed in a shared Continuous Integration (CI) environment. The work needed to create such a CI environment is nontrivial, and is outside the scope of this core workflow overview. This longer iteration cycle of committing changes to version control and then waiting for the CI pipeline to execute is often lengthy enough to prohibit using speculative plans as a feedback loop while authoring individual OpenTofu configuration changes. Speculative plans are still useful before new OpenTofu changes are applied or even merged to the main development branch, however, as we'll see in a minute. ### Plan[​](https://opentofu.org/docs/v1.10/intro/core-workflow/#plan-1 "Direct link to Plan") For teams collaborating on infrastructure, OpenTofu's plan output creates an opportunity for team members to review each other's work. This allows the team to ask questions, evaluate risks, and catch mistakes before any potentially harmful changes are made. The natural place for these reviews to occur is alongside pull requests within version control--the point at which an individual proposes a merge from their working branch to the shared team branch. If team members review proposed config changes alongside speculative plan output, they can evaluate whether the intent of the change is being achieved by the plan. The problem becomes producing that speculative plan output for the team to review. Some teams that still run OpenTofu locally make a practice that pull requests should include an attached copy of speculative plan output generated by the change author. Others arrange for their CI system to post speculative plan output to pull requests automatically. In addition to reviewing the plan for the proper expression of its author's intent, the team can also make an evaluation whether they want this change to happen now. For example, if a team notices that a certain change could result in service disruption, they may decide to delay merging its pull request until they can schedule a maintenance window. ### Apply[​](https://opentofu.org/docs/v1.10/intro/core-workflow/#apply-1 "Direct link to Apply") Once a pull request has been approved and merged, it's important for the team to review the final concrete plan that's run against the shared team branch and the latest version of the state file. This plan has the potential to be different than the one reviewed on the pull request due to issues like merge order or recent infrastructural changes. For example, if a manual change was made to your infrastructure since the plan was reviewed, the plan might be different when you merge. It is at this point that the team asks questions about the potential implications of applying the change. Do we expect any service disruption from this change? Is there any part of this change that is high risk? Is there anything in our system that we should be watching as we apply this? Is there anyone we need to notify that this change is happening? Depending on the change, sometimes team members will want to watch the apply output as it is happening. For teams that are running OpenTofu locally, this may involve a screen share with the team. For teams running OpenTofu in CI, this may involve gathering around the build log. Just like the workflow for individuals, the core workflow for teams is a loop that plays out for each change. For some teams this loop happens a few times a week, for others, many times a day. Conclusion[​](https://opentofu.org/docs/v1.10/intro/core-workflow/#conclusion "Direct link to Conclusion") ----------------------------------------------------------------------------------------------------------- There are many different ways to use OpenTofu: as an individual user, a single team, or an entire organization at scale. Choosing the best approach for the density of collaboration needed will provide the most return on your investment in the core OpenTofu workflow. For organizations using OpenTofu at scale, [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software) introduces new layers that build on this core workflow to solve problems unique to teams and organizations. * [Working as an Individual Practitioner](https://opentofu.org/docs/v1.10/intro/core-workflow/#working-as-an-individual-practitioner) * [Write](https://opentofu.org/docs/v1.10/intro/core-workflow/#write) * [Plan](https://opentofu.org/docs/v1.10/intro/core-workflow/#plan) * [Apply](https://opentofu.org/docs/v1.10/intro/core-workflow/#apply) * [Working as a Team](https://opentofu.org/docs/v1.10/intro/core-workflow/#working-as-a-team) * [Write](https://opentofu.org/docs/v1.10/intro/core-workflow/#write-1) * [Plan](https://opentofu.org/docs/v1.10/intro/core-workflow/#plan-1) * [Apply](https://opentofu.org/docs/v1.10/intro/core-workflow/#apply-1) * [Conclusion](https://opentofu.org/docs/v1.10/intro/core-workflow/#conclusion) --- # Command: version | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/version/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: version ================ The `tofu version` displays the current version of OpenTofu and all installed plugins. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/version/#usage "Direct link to Usage") --------------------------------------------------------------------------------------------- Usage: `tofu version [options]` With no additional arguments, `version` will display the version of OpenTofu, the platform it's installed on, and installed providers. This command has one optional flag: * `-json` - If specified, the version information is formatted as a JSON object, and no upgrade or security information is included. Example[​](https://opentofu.org/docs/v1.10/cli/commands/version/#example "Direct link to Example") --------------------------------------------------------------------------------------------------- Basic usage, with security information shown if relevant: Code Block $ tofu versionOpenTofu v1.6.0on darwin_amd64+ provider registry.opentofu.org/hashicorp/null v3.0.0 As JSON: Code Block $ tofu version -json{ "terraform_version": "0.16.0-alpha2", "platform": "darwin_amd64", "provider_selections": { "registry.opentofu.org/hashicorp/null": "3.0.0" }} * [Usage](https://opentofu.org/docs/v1.10/cli/commands/version/#usage) * [Example](https://opentofu.org/docs/v1.10/cli/commands/version/#example) --- # Command: state show | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/state/show/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state show =================== The `tofu state show` command is used to show the attributes of a single resource in the [OpenTofu state](https://opentofu.org/docs/v1.10/language/state/) . Usage[​](https://opentofu.org/docs/v1.10/cli/commands/state/show/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------ Usage: `tofu state show [options] ADDRESS` The command will show the attributes of a single resource in the state file that matches the given address. This command requires an address that points to a single resource in the state. Addresses are in [resource addressing format](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/) . Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu show`. The command-line flags are all optional. The following flags are available: * `-state=path` - Path to the state file. Defaults to "terraform.tfstate". Ignored when [remote state](https://opentofu.org/docs/v1.10/language/state/remote/) is used. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. * `-show-sensitive` - If specified, sensitive values will be displayed. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. The output of `tofu state show` is intended for human consumption, not programmatic consumption. To extract state data for use in other software, use [`tofu show -json`](https://opentofu.org/docs/v1.10/cli/commands/show/#json-output) and decode the result using the documented structure. Example: Show a Resource[​](https://opentofu.org/docs/v1.10/cli/commands/state/show/#example-show-a-resource "Direct link to Example: Show a Resource") -------------------------------------------------------------------------------------------------------------------------------------------------------- The example below shows a `packet_device` resource named `worker`: Code Block $ tofu state show 'packet_device.worker'# packet_device.worker:resource "packet_device" "worker" { billing_cycle = "hourly" created = "2015-12-17T00:06:56Z" facility = "ewr1" hostname = "prod-xyz01" id = "6015bg2b-b8c4-4925-aad2-f0671d5d3b13" locked = false} Example: Show a Module Resource[​](https://opentofu.org/docs/v1.10/cli/commands/state/show/#example-show-a-module-resource "Direct link to Example: Show a Module Resource") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The example below shows a `packet_device` resource named `worker` inside a module named `foo`: Code Block $ tofu state show 'module.foo.packet_device.worker' Example: Show a Resource configured with count[​](https://opentofu.org/docs/v1.10/cli/commands/state/show/#example-show-a-resource-configured-with-count "Direct link to Example: Show a Resource configured with count") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The example below shows the first instance of a `packet_device` resource named `worker` configured with [`count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) : Code Block $ tofu state show 'packet_device.worker[0]' Example: Show a Resource configured with for\_each[​](https://opentofu.org/docs/v1.10/cli/commands/state/show/#example-show-a-resource-configured-with-for_each "Direct link to Example: Show a Resource configured with for_each") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ The following example shows the `"example"` instance of a `packet_device` resource named `worker` configured with the [`for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) meta-argument. You must place the resource name in single quotes when it contains special characters like double quotes. Linux, Mac OS, and UNIX: Code Block $ tofu state show 'packet_device.worker["example"]' PowerShell: Code Block $ tofu state show 'packet_device.worker[\"example\"]' Windows `cmd.exe`: Code Block $ tofu state show packet_device.worker[\"example\"] * [Usage](https://opentofu.org/docs/v1.10/cli/commands/state/show/#usage) * [Example: Show a Resource](https://opentofu.org/docs/v1.10/cli/commands/state/show/#example-show-a-resource) * [Example: Show a Module Resource](https://opentofu.org/docs/v1.10/cli/commands/state/show/#example-show-a-module-resource) * [Example: Show a Resource configured with count](https://opentofu.org/docs/v1.10/cli/commands/state/show/#example-show-a-resource-configured-with-count) * [Example: Show a Resource configured with for\_each](https://opentofu.org/docs/v1.10/cli/commands/state/show/#example-show-a-resource-configured-with-for_each) --- # Command: untaint | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/untaint/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: untaint ================ OpenTofu has a marker called "tainted" which it uses to track that an object might be damaged and so a future OpenTofu plan ought to replace it. OpenTofu automatically marks an object as "tainted" if an error occurs during a multi-step "create" action, because OpenTofu can't be sure that the object was left in a fully-functional state. You can also manually mark an object as "tainted" using the deprecated command [`tofu taint`](https://opentofu.org/docs/v1.10/cli/commands/taint/) , although we no longer recommend that workflow. If OpenTofu currently considers a particular object as tainted but you've determined that it's actually functioning correctly and need _not_ be replaced, you can use `tofu untaint` to remove the taint marker from that object. This command _will not_ modify any real remote objects, but will modify the state in order to remove the tainted status. If you remove the taint marker from an object but then later discover that it was degraded after all, you can create and apply a plan to replace it without first re-tainting the object, by using a command like the following: Code Block tofu apply -replace="aws_instance.example[0]" Usage[​](https://opentofu.org/docs/v1.10/cli/commands/untaint/#usage "Direct link to Usage") --------------------------------------------------------------------------------------------- Usage: `tofu untaint [options] address` The `address` argument is a [resource address](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/) identifying a particular resource instance which is currently tainted. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu untaint`. This command also accepts the following options: * `-allow-missing` - If specified, the command will succeed (exit code 0) even if the resource is missing. The command might still return an error for other situations, such as if there is a problem reading or writing the state. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * `-no-color` - Disables terminal formatting sequences in the output. Use this if you are running OpenTofu in a context where its output will be rendered by a system that cannot interpret terminal formatting. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.10/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.10/language/settings/backends/remote/) only, `tofu untaint` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/v1.10/cli/cloud/command-line-arguments/#ignore-remote-version) . For configurations using [the `local` backend](https://opentofu.org/docs/v1.10/language/settings/backends/local/) only, `tofu untaint` also accepts the legacy options [`-state`, `-state-out`, and `-backup`](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) . * [Usage](https://opentofu.org/docs/v1.10/cli/commands/untaint/#usage) --- # Command: workspace delete | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/workspace/delete/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: workspace delete ========================= The `tofu workspace delete` command is used to delete an existing workspace. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/workspace/delete/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------------ Usage: `tofu workspace delete [OPTIONS] NAME [DIR]` This command will delete the specified workspace. To delete a workspace, it must already exist, it must not be tracking resources, and it must not be your current workspace. If the workspace is tracking resources, OpenTofu will not allow you to delete it unless the `-force` flag is specified. Additionally, different [backends](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#backend-types) may implement other restrictions on whether a workspace is considered safe to delete without the `-force` flag, such as whether the workspace is locked. If you delete a workspace which is tracking resources (via `-force`), then resources may become "dangling". These are resources that physically exist but that OpenTofu can no longer manage. This is sometimes preferred: you may want OpenTofu to stop managing resources, so they can be managed some other way. Most of the time, however, this is not intended and so OpenTofu protects you from getting into this situation. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu workspace delete`. The command-line flags are all optional. The only supported flags are: * `-force` - Delete the workspace even if it is tracking resources. After deletion, OpenTofu can no longer track or manage the workspace's infrastructure. Defaults to false. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Duration to retry a state lock. Default 0s. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. Example[​](https://opentofu.org/docs/v1.10/cli/commands/workspace/delete/#example "Direct link to Example") ------------------------------------------------------------------------------------------------------------ Code Block $ tofu workspace delete exampleDeleted workspace "example". * [Usage](https://opentofu.org/docs/v1.10/cli/commands/workspace/delete/#usage) * [Example](https://opentofu.org/docs/v1.10/cli/commands/workspace/delete/#example) --- # Command: workspace new | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/workspace/new/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: workspace new ====================== The `tofu workspace new` command is used to create a new workspace. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/workspace/new/#usage "Direct link to Usage") --------------------------------------------------------------------------------------------------- Usage: `tofu workspace new [OPTIONS] NAME [DIR]` This command will create a new workspace with the given name. A workspace with this name must not already exist. If the `-state` flag is given, the state specified by the given path will be copied to initialize the state for this new workspace. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu workspace new`. The command-line flags are all optional. The supported flags are: * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Duration to retry a state lock. Default 0s. * `-state=path` - Path to an existing state file to initialize the state of this environment. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. Example: Create[​](https://opentofu.org/docs/v1.10/cli/commands/workspace/new/#example-create "Direct link to Example: Create") -------------------------------------------------------------------------------------------------------------------------------- Code Block $ tofu workspace new exampleCreated and switched to workspace "example"!You're now on a new, empty workspace. Workspaces isolate their state,so if you run "tofu plan" OpenTofu will not see any existing statefor this configuration. Example: Create from State[​](https://opentofu.org/docs/v1.10/cli/commands/workspace/new/#example-create-from-state "Direct link to Example: Create from State") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- To create a new workspace from a pre-existing local state file: Code Block $ tofu workspace new -state=old.terraform.tfstate exampleCreated and switched to workspace "example".You're now on a new, empty workspace. Workspaces isolate their state,so if you run "tofu plan" OpenTofu will not see any existing statefor this configuration. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/workspace/new/#usage) * [Example: Create](https://opentofu.org/docs/v1.10/cli/commands/workspace/new/#example-create) * [Example: Create from State](https://opentofu.org/docs/v1.10/cli/commands/workspace/new/#example-create-from-state) --- # Command: state rm | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state rm ================= The main function of [OpenTofu state](https://opentofu.org/docs/v1.10/language/state/) is to track the bindings between resource instance addresses in your configuration and the remote objects they represent. Normally OpenTofu automatically updates the state in response to actions taken when applying a plan, such as removing a binding for a remote object that has now been deleted. You can use `tofu state rm` in the less common situation where you wish to remove a binding to an existing remote object without first destroying it, which will effectively make OpenTofu "forget" the object while it continues to exist in the remote system. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#usage "Direct link to Usage") ---------------------------------------------------------------------------------------------- Usage: `tofu state rm [options] ADDRESS...` OpenTofu will search the state for any instances matching the given [resource address](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/) , and remove the record of each one so that OpenTofu will no longer be tracking the corresponding remote objects. This means that although the objects will still continue to exist in the remote system, a subsequent [`tofu plan`](https://opentofu.org/docs/v1.10/cli/commands/plan/) will include an action to create a new object for each of the "forgotten" instances. Depending on the constraints imposed by the remote system, creating those objects might fail if their names or other identifiers conflict with the old objects still present. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu state rm`. This command also accepts the following options: * `-dry-run` - Report all of the resource instances that match the given address without actually "forgetting" any of them. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.10/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.10/language/settings/backends/remote/) only, `tofu state rm` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/v1.10/cli/cloud/command-line-arguments/#ignore-remote-version) . For configurations using [the `local` state rm](https://opentofu.org/docs/v1.10/language/settings/backends/local/) only, `tofu state rm` also accepts the legacy options [`-state`, `-state-out`, and `-backup`](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) . Example: Remove all Instances of a Resource[​](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#example-remove-all-instances-of-a-resource "Direct link to Example: Remove all Instances of a Resource") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The following example will cause OpenTofu to "forget" all of the instances of the `packet_device` resource named "worker". Code Block $ tofu state rm 'packet_device.worker' A resource that doesn't use `count` or `for_each` has only one instance, so this is also the appropriate syntax to select that single instance. Example: Remove all Instances of a Resource in a Module[​](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#example-remove-all-instances-of-a-resource-in-a-module "Direct link to Example: Remove all Instances of a Resource in a Module") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To select a resource that you've defined in a child module you must specify the path of that module as part of the resource address: Code Block $ tofu state rm 'module.foo.packet_device.worker' Example: Remove all Instances of all Resources in a Module[​](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#example-remove-all-instances-of-all-resources-in-a-module "Direct link to Example: Remove all Instances of all Resources in a Module") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ The following example will cause OpenTofu to "forget" all of the instances associated with all resources defined in all instances of the module named `foo`: Code Block $ tofu state rm 'module.foo' Example: Remove a Particular Instance of a Resource using `count`[​](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#example-remove-a-particular-instance-of-a-resource-using-count "Direct link to example-remove-a-particular-instance-of-a-resource-using-count") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A resource defined with [the `count` meta-argument](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) has multiple instances that are each identified by an integer. You can select a particular instance by including an explicit index in your given address: Code Block $ tofu state rm 'packet_device.worker[0]' Brackets (`[`, `]`) have a special meaning in some shells, so you may need to quote or escape the address in order to pass it literally to OpenTofu. The above shows the typical quoting syntax for Unix-style shells. Example: Remove a Particular Instance of a Resource using `for_each`[​](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#example-remove-a-particular-instance-of-a-resource-using-for_each "Direct link to example-remove-a-particular-instance-of-a-resource-using-for_each") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A resource defined with [the `for_each` meta-argument](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) has multiple instances that are each identified by an string. You can select a particular instance by including an explicit key in your given address. However, the syntax for strings includes quotes and the quote symbol often has special meaning in command shells, so you'll need to use the appropriate quoting and/or escaping syntax for the shell you are using. For example: Unix-style shells, such as on Linux or macOS: Code Block $ tofu state rm 'packet_device.worker["example"]' Windows Command Prompt (`cmd.exe`): Code Block $ tofu state rm packet_device.worker[\"example\"] PowerShell: Code Block $ tofu state rm 'packet_device.worker[\"example\"]' * [Usage](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#usage) * [Example: Remove all Instances of a Resource](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#example-remove-all-instances-of-a-resource) * [Example: Remove all Instances of a Resource in a Module](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#example-remove-all-instances-of-a-resource-in-a-module) * [Example: Remove all Instances of all Resources in a Module](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#example-remove-all-instances-of-all-resources-in-a-module) * [Example: Remove a Particular Instance of a Resource using `count`](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#example-remove-a-particular-instance-of-a-resource-using-count) * [Example: Remove a Particular Instance of a Resource using `for_each`](https://opentofu.org/docs/v1.10/cli/commands/state/rm/#example-remove-a-particular-instance-of-a-resource-using-for_each) --- # Command: state mv | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state mv ================= The main function of [OpenTofu state](https://opentofu.org/docs/v1.10/language/state/) is to track the bindings between resource instance addresses in your configuration and the remote objects they represent. Normally OpenTofu automatically updates the state in response to actions taken when applying a plan, such as removing a binding for an remote object that has now been deleted. You can use `tofu state mv` in the less common situation where you wish to retain an existing remote object but track it as a different resource instance address in OpenTofu, such as if you have renamed a resource block or you have moved it into a different module in your configuration. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#usage "Direct link to Usage") ---------------------------------------------------------------------------------------------- Usage: `tofu state mv [options] SOURCE DESTINATION` OpenTofu will look in the current state for a resource instance, resource, or module that matches the given address, and if successful it will move the remote objects currently associated with the source to be tracked instead by the destination. Both the source and destination addresses must use [resource address syntax](https://opentofu.org/docs/v1.10/cli/state/resource-addressing/) , and they must both refer to the same kind of object: you can only move a resource instance to another resource instance, a whole module instance to another whole module instance, etc. Furthermore, if you are moving a resource or a resource instance then you can only move it to a new address with the same resource type. The most common uses for `tofu state mv` are when you have renamed a resource block in your configuration or you've moved a resource block into a child module, in both cases with the intention of retaining the existing object but tracking it under a new name. By default OpenTofu will understand moving or renaming a resource configuration as a request to delete the old object and create a new object at the new address, and so `tofu state mv` allows you to override that interpretation by pre-emptively attaching the existing object to the new address in OpenTofu. Warning If you are using OpenTofu in a collaborative environment, you must ensure that when you are using `tofu state mv` for a code refactoring purpose you communicate carefully with your coworkers to ensure that nobody makes any other changes between your configuration change and your `tofu state mv` command, because otherwise they might inadvertently create a plan that will destroy the old object and create a new object at the new address. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu state mv`. This command also accepts the following options: * `-dry-run` - Report all of the resource instances that match the given address without actually "forgetting" any of them. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.10/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.10/language/settings/backends/remote/) only, `tofu state mv` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/v1.10/cli/cloud/command-line-arguments/#ignore-remote-version) . The legacy options [`-backup` and `-backup-out`](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) operate on a local state file only. Configurations using [the `remote` backend](https://opentofu.org/docs/v1.10/language/settings/backends/remote/) must specify a local state file with the [`-state`](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) option in order to use the [`-backup` and `-backup-out`](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) options. For configurations using [the `local` state mv](https://opentofu.org/docs/v1.10/language/settings/backends/local/) only, `tofu state mv` also accepts the legacy options [`-state`, `-state-out`, `-backup`, and `-backup-out`](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) . Example: Rename a Resource[​](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#example-rename-a-resource "Direct link to Example: Rename a Resource") ------------------------------------------------------------------------------------------------------------------------------------------------------------ Renaming a resource means making a configuration change like the following: Code Block -resource "packet_device" "worker" {+resource "packet_device" "helper" { # ... } To tell OpenTofu that it should treat the new "helper" resource as a rename of the old "worker" resource, you can pair the above configuration change with the following command: Code Block tofu state mv packet_device.worker packet_device.helper Example: Move a Resource Into a Module[​](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#example-move-a-resource-into-a-module "Direct link to Example: Move a Resource Into a Module") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ If you originally wrote a resource in your root module but now wish to refactor it into a child module, you can move the `resource` block into the child module configuration, removing the original in the root module, and then run the following command to tell OpenTofu to treat it as a move: Code Block tofu state mv packet_device.worker module.worker.packet_device.worker In the above example the new resource has the same name but a different module address. You could also change the resource name at the same time, if the new module organization suggests a different naming scheme: Code Block tofu state mv packet_device.worker module.worker.packet_device.main Example: Move a Module Into a Module[​](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#example-move-a-module-into-a-module "Direct link to Example: Move a Module Into a Module") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ You can also refactor an entire module into a child module. In the configuration, move the `module` block representing the module into a different module and then pair that change with a command like the following: Code Block tofu state mv module.app module.parent.module.app Example: Move a Particular Instance of a Resource using `count`[​](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#example-move-a-particular-instance-of-a-resource-using-count "Direct link to example-move-a-particular-instance-of-a-resource-using-count") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A resource defined with [the `count` meta-argument](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) has multiple instances that are each identified by an integer. You can select a particular instance by including an explicit index in your given address: Code Block $ tofu state mv 'packet_device.worker[0]' 'packet_device.helper[0]' A resource that doesn't use `count` or `for_each` has only a single resource instance whose address is the same as the resource itself, and so you can move from an address not containing an index to an address containing an index, or the opposite, as long as the address type you use matches whether and how each resource is configured: Code Block $ tofu state mv 'packet_device.main' 'packet_device.all[0]' Brackets (`[`, `]`) have a special meaning in some shells, so you may need to quote or escape the address in order to pass it literally to OpenTofu. The above examples show the typical quoting syntax for Unix-style shells. Example: Move a Resource configured with for\_each[​](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#example-move-a-resource-configured-with-for_each "Direct link to Example: Move a Resource configured with for_each") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A resource defined with [the `for_each` meta-argument](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) has multiple instances that are each identified by an string. You can select a particular instance by including an explicit key in your given address. However, the syntax for strings includes quotes and the quote symbol often has special meaning in command shells, so you'll need to use the appropriate quoting and/or escaping syntax for the shell you are using. For example: Unix-style shells, such as on Linux or macOS: Code Block tofu state mv 'packet_device.worker["example123"]' 'packet_device.helper["example456"]' Windows Command Prompt (`cmd.exe`): Code Block tofu state mv packet_device.worker[\"example123\"] packet_device.helper[\"example456\"] PowerShell: Code Block tofu state mv 'packet_device.worker[\"example123\"]' 'packet_device.helper[\"example456\"]' Aside from the use of strings instead of integers for instance keys, the treatment of `for_each` resources is similar to `count` resources and so the same combinations of addresses with and without index components is valid as described in the previous section. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#usage) * [Example: Rename a Resource](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#example-rename-a-resource) * [Example: Move a Resource Into a Module](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#example-move-a-resource-into-a-module) * [Example: Move a Module Into a Module](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#example-move-a-module-into-a-module) * [Example: Move a Particular Instance of a Resource using `count`](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#example-move-a-particular-instance-of-a-resource-using-count) * [Example: Move a Resource configured with for\_each](https://opentofu.org/docs/v1.10/cli/commands/state/mv/#example-move-a-resource-configured-with-for_each) --- # Command: workspace list | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/workspace/list/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: workspace list ======================= The `tofu workspace list` command is used to list all existing workspaces. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/workspace/list/#usage "Direct link to Usage") ---------------------------------------------------------------------------------------------------- Usage: `tofu workspace list [DIR]` The command will list all existing workspaces. The current workspace is indicated using an asterisk (`*`) marker. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu workspace list`. This command also accepts the following options: * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. Example[​](https://opentofu.org/docs/v1.10/cli/commands/workspace/list/#example "Direct link to Example") ---------------------------------------------------------------------------------------------------------- Code Block $ tofu workspace list default* development jsmith-test * [Usage](https://opentofu.org/docs/v1.10/cli/commands/workspace/list/#usage) * [Example](https://opentofu.org/docs/v1.10/cli/commands/workspace/list/#example) --- # Remote Service Discovery | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Remote Service Discovery ======================== OpenTofu implements much of its functionality in terms of remote services. While in many cases these are generic third-party services that are useful to many applications, some of these services are tailored specifically to OpenTofu's needs. We call these _OpenTofu-native services_, and OpenTofu interacts with them via the remote service discovery protocol described below. User-facing Hostname[​](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/#user-facing-hostname "Direct link to User-facing Hostname") -------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu-native services are provided, from a user's perspective, at a user-facing "friendly hostname" which serves as the key for configuration and for any authentication credentials required. The discovery protocol's purpose is to map from a user-provided hostname to the base URL of a particular service. Each host can provide different combinations of services -- or no services at all! -- and so the discovery protocol has a secondary purpose of allowing OpenTofu to identify _which_ services are valid for a given hostname. For example, module source strings can include a module registry hostname as their first segment, like `example.com/namespace/name/provider`, and OpenTofu uses service discovery to determine whether `example.com` _has_ a module registry, and if so where its API is available. A user-facing hostname is a fully-specified [internationalized domain name](https://en.wikipedia.org/wiki/Internationalized_domain_name) expressed in its Unicode form (the corresponding "punycode" form is not allowed) which must be resolvable in DNS to an address that has an HTTPS server running on port 443. User-facing hostnames are normalized for internal comparison using the standard Unicode [Nameprep](https://en.wikipedia.org/wiki/Nameprep) algorithm, which includes converting all letters to lowercase, normalizing combining diacritics to precomposed form where possible, and various other normalization steps. Discovery Process[​](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/#discovery-process "Direct link to Discovery Process") ----------------------------------------------------------------------------------------------------------------------------------------------- Given a hostname, discovery begins by forming an initial discovery URL using that hostname with the `https:` scheme and the fixed path `/.well-known/terraform.json`. For example, given the hostname `example.com` the initial discovery URL would be `https://example.com/.well-known/terraform.json`. OpenTofu then sends a `GET` request to this discovery URL and expects a JSON response. If the response does not have status 200, does not have a media type of `application/json` or, if the body cannot be parsed as a JSON object, then discovery fails and OpenTofu considers the host to not support _any_ OpenTofu-native services. If the response is an HTTP redirect then OpenTofu repeats this step with the new location as its discovery URL. OpenTofu is guaranteed to follow at least one redirect, but nested redirects are not guaranteed nor recommended. If the response is a valid JSON object then its keys are OpenTofu native service identifiers, consisting of a service type name and a version string separated by a period. For example, the service identifier for version 1 of the module registry protocol is `modules.v1`. The value of each object element is the base URL for the service in question. This URL may be either absolute or relative, and if relative it is resolved against the final discovery URL (_after_ following redirects). The following is an example discovery document declaring support for version 1 of the module registry protocol: Code Block { "modules.v1": "https://modules.example.com/v1/"} Supported Services[​](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/#supported-services "Direct link to Supported Services") -------------------------------------------------------------------------------------------------------------------------------------------------- At present, the following service identifiers are in use: * `login.v1`: [login protocol version 1](https://opentofu.org/docs/v1.10/cli/commands/login/) * `modules.v1`: [module registry API version 1](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/) * `providers.v1`: [provider registry API version 1](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/) Authentication[​](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/#authentication "Direct link to Authentication") -------------------------------------------------------------------------------------------------------------------------------------- If credentials for the given hostname are available in [the CLI config](https://opentofu.org/docs/v1.10/cli/config/config-file/#Credentials) through a `credentials_helper` or a host-specific environment variable, then they will be included in the request for the discovery document. The credentials may also be provided to endpoints declared in the discovery document, depending on the requirements of the service in question. Non-standard Ports in User-facing Hostnames[​](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/#non-standard-ports-in-user-facing-hostnames "Direct link to Non-standard Ports in User-facing Hostnames") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- It is strongly recommended to provide the discovery document for a hostname on the standard HTTPS port 443. However, in development environments this is not always possible or convenient, so OpenTofu allows a hostname to end with a port specification consisting of a colon followed by one or more decimal digits. When a custom port number is present, the service on that port is expected to implement HTTPS and respond to the same fixed discovery path. For day-to-day use it is strongly recommended _not_ to rely on this mechanism and to instead provide the discovery document on the standard port, since this allows use of the most user-friendly hostname form. * [User-facing Hostname](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/#user-facing-hostname) * [Discovery Process](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/#discovery-process) * [Supported Services](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/#supported-services) * [Authentication](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/#authentication) * [Non-standard Ports in User-facing Hostnames](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/#non-standard-ports-in-user-facing-hostnames) --- # Command: workspace select | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/workspace/select/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: workspace select ========================= The `tofu workspace select` command is used to choose a different workspace to use for further operations. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/workspace/select/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------------ Usage: `tofu workspace select NAME [DIR]` This command will select another workspace. The named workspace must already exist. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu workspace select`. The supported flags are: * `-or-create` - If the workspace that is being selected does not exist, create it. Default is `false`. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. Example[​](https://opentofu.org/docs/v1.10/cli/commands/workspace/select/#example "Direct link to Example") ------------------------------------------------------------------------------------------------------------ Code Block $ tofu workspace list default* development jsmith-test$ tofu workspace select defaultSwitched to workspace "default". * [Usage](https://opentofu.org/docs/v1.10/cli/commands/workspace/select/#usage) * [Example](https://opentofu.org/docs/v1.10/cli/commands/workspace/select/#example) --- # OpenTelemetry Tracing | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/tracing/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page OpenTelemetry Tracing ===================== Experimental Feature OpenTelemetry tracing support is experimental and may change in future releases. OpenTofu 1.10.0 introduces support for [OpenTelemetry](https://opentelemetry.io/) (OTel) tracing, providing visibility into OpenTofu's internal operations. This feature helps you debug performance issues, understand operation flows, and optimize your infrastructure workflows. Privacy and Security[​](https://opentofu.org/docs/v1.10/internals/tracing/#privacy-and-security "Direct link to Privacy and Security") --------------------------------------------------------------------------------------------------------------------------------------- OpenTofu's tracing implementation is designed with privacy as the top priority: * **Opt-in only**: Tracing is completely disabled by default * **Local-only**: No telemetry data is sent to OpenTofu or any external service unless you explicitly configure it * **Your infrastructure**: You control where traces are sent using standard OpenTelemetry configuration * **Zero overhead**: When disabled, tracing has no performance impact As the OpenTofu team emphasizes: "Although this builds on a project named Open_Telemetry_, we are adding this support explicitly for you to trace _your application_ using _your tooling_ on _your infrastructure_." This feature is not intended to collect any data about OpenTofu usage patterns or user behavior for the OpenTofu project itself. Quick Start[​](https://opentofu.org/docs/v1.10/internals/tracing/#quick-start "Direct link to Quick Start") ------------------------------------------------------------------------------------------------------------ ### 1\. Set up a tracing backend[​](https://opentofu.org/docs/v1.10/internals/tracing/#1-set-up-a-tracing-backend "Direct link to 1. Set up a tracing backend") The easiest way to get started is with [Jaeger](https://www.jaegertracing.io/) , an open-source distributed tracing platform: Code Block docker run -d --rm --name jaeger \ -p 16686:16686 \ -p 4317:4317 \ -p 4318:4318 \ jaegertracing/jaeger:latest ### 2\. Configure OpenTofu[​](https://opentofu.org/docs/v1.10/internals/tracing/#2-configure-opentofu "Direct link to 2. Configure OpenTofu") Enable tracing by setting these environment variables: Code Block # Enable OTLP trace exporterexport OTEL_TRACES_EXPORTER=otlp# Point to your Jaeger instanceexport OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317# Required for local development (skip TLS verification)export OTEL_EXPORTER_OTLP_INSECURE=true ### 3\. Run OpenTofu commands[​](https://opentofu.org/docs/v1.10/internals/tracing/#3-run-opentofu-commands "Direct link to 3. Run OpenTofu commands") Now any OpenTofu command will generate traces: Code Block tofu init # Traces provider downloadstofu plan # Traces planning operationstofu apply # Traces apply workflow ### 4\. View traces[​](https://opentofu.org/docs/v1.10/internals/tracing/#4-view-traces "Direct link to 4. View traces") Open your browser and navigate to [http://localhost:16686](http://localhost:16686/) to access the Jaeger UI. You'll see your OpenTofu operations broken down into detailed traces. Configuration Options[​](https://opentofu.org/docs/v1.10/internals/tracing/#configuration-options "Direct link to Configuration Options") ------------------------------------------------------------------------------------------------------------------------------------------ OpenTofu supports standard OpenTelemetry environment variables for configuration: ### Basic Configuration[​](https://opentofu.org/docs/v1.10/internals/tracing/#basic-configuration "Direct link to Basic Configuration") | Variable | Description | Example | | --- | --- | --- | | `OTEL_TRACES_EXPORTER` | Must be set to `otlp` to enable tracing | `otlp` | | `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP endpoint URL | `http://localhost:4317` | | `OTEL_EXPORTER_OTLP_INSECURE` | Skip TLS verification | `true` for local dev | Additional OTLP configuration options are supported. See the [OpenTelemetry documentation](https://opentelemetry.io/docs/specs/otel/protocol/exporter/#configuration-options) for details. Note In this experimental implementation, OpenTofu always samples 100% of traces when tracing is enabled. Sampling configuration is not currently supported. Integration with Observability Platforms[​](https://opentofu.org/docs/v1.10/internals/tracing/#integration-with-observability-platforms "Direct link to Integration with Observability Platforms") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- While Jaeger is great for getting started, OpenTofu's OpenTelemetry support works with any OTLP-compatible backend such as Grafana Tempo, AWS X-Ray, or Datadog. Use Cases[​](https://opentofu.org/docs/v1.10/internals/tracing/#use-cases "Direct link to Use Cases") ------------------------------------------------------------------------------------------------------ ### Debugging Slow Operations[​](https://opentofu.org/docs/v1.10/internals/tracing/#debugging-slow-operations "Direct link to Debugging Slow Operations") Tracing helps identify bottlenecks in your OpenTofu workflows: * Which provider downloads are slowest? * How long does each resource take to plan/apply? * Where is time being spent during initialization? ### CI/CD Pipeline Optimization[​](https://opentofu.org/docs/v1.10/internals/tracing/#cicd-pipeline-optimization "Direct link to CI/CD Pipeline Optimization") In continuous integration environments, tracing can reveal: * Parallel operation conflicts * Cache effectiveness * Network latency issues * Lock contention problems ### Multi-Environment Deployments[​](https://opentofu.org/docs/v1.10/internals/tracing/#multi-environment-deployments "Direct link to Multi-Environment Deployments") For complex deployments across regions or environments: * Compare performance across different backends * Identify region-specific delays * Track provider version update impacts Future Development[​](https://opentofu.org/docs/v1.10/internals/tracing/#future-development "Direct link to Future Development") --------------------------------------------------------------------------------------------------------------------------------- This experimental feature is actively being developed. The OpenTofu team is particularly interested in feedback about: * Which additional operations should be traced * Performance impact in real-world scenarios * Integration experiences with different backends * Specific use cases that benefit from tracing Please share your feedback through [GitHub issues](https://github.com/opentofu/opentofu/issues) or the [OpenTofu Slack community](https://opentofu.org/slack) . * [Privacy and Security](https://opentofu.org/docs/v1.10/internals/tracing/#privacy-and-security) * [Quick Start](https://opentofu.org/docs/v1.10/internals/tracing/#quick-start) * [1\. Set up a tracing backend](https://opentofu.org/docs/v1.10/internals/tracing/#1-set-up-a-tracing-backend) * [2\. Configure OpenTofu](https://opentofu.org/docs/v1.10/internals/tracing/#2-configure-opentofu) * [3\. Run OpenTofu commands](https://opentofu.org/docs/v1.10/internals/tracing/#3-run-opentofu-commands) * [4\. View traces](https://opentofu.org/docs/v1.10/internals/tracing/#4-view-traces) * [Configuration Options](https://opentofu.org/docs/v1.10/internals/tracing/#configuration-options) * [Basic Configuration](https://opentofu.org/docs/v1.10/internals/tracing/#basic-configuration) * [Integration with Observability Platforms](https://opentofu.org/docs/v1.10/internals/tracing/#integration-with-observability-platforms) * [Use Cases](https://opentofu.org/docs/v1.10/internals/tracing/#use-cases) * [Debugging Slow Operations](https://opentofu.org/docs/v1.10/internals/tracing/#debugging-slow-operations) * [CI/CD Pipeline Optimization](https://opentofu.org/docs/v1.10/internals/tracing/#cicd-pipeline-optimization) * [Multi-Environment Deployments](https://opentofu.org/docs/v1.10/internals/tracing/#multi-environment-deployments) * [Future Development](https://opentofu.org/docs/v1.10/internals/tracing/#future-development) --- # Migrating to OpenTofu from Terraform | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/migration/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Migrating to OpenTofu from Terraform ==================================== Before you begin[​](https://opentofu.org/docs/v1.10/intro/migration/#before-you-begin "Direct link to Before you begin") ------------------------------------------------------------------------------------------------------------------------- OpenTofu aims to maintain compatibility with Terraform configurations. While most Terraform code will work without modification, we recommend following our [migration guide](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/) to ensure a smooth transition. Migration process overview[​](https://opentofu.org/docs/v1.10/intro/migration/#migration-process-overview "Direct link to Migration process overview") ------------------------------------------------------------------------------------------------------------------------------------------------------- The migration process is designed to be safe and reversible: 1. **Back up your infrastructure state and code** 2. **Install OpenTofu** 3. **Initialize and verify your configuration** 4. **Test with a small change** [β†’ Read the complete migration guide](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/) * [Before you begin](https://opentofu.org/docs/v1.10/intro/migration/#before-you-begin) * [Migration process overview](https://opentofu.org/docs/v1.10/intro/migration/#migration-process-overview) --- # Command: validate | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/cli/commands/validate/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: validate ================= The `tofu validate` command validates the configuration files in a directory, referring only to the configuration and not accessing any remote services such as remote state, provider APIs, etc. Note Use of [variables in module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu validate`. Validate runs checks that verify whether a configuration is syntactically valid and internally consistent, regardless of existing state. It is thus primarily useful for general verification of reusable modules, including correctness of attribute names and value types. Warning Validate does not have access to the existing state, validation checks that require state access will be skipped. It is safe to run this command automatically, for example as a post-save check in a text editor or as a test step for a re-usable module in a CI system. Validation requires an initialized working directory with any referenced plugins and modules installed. To initialize a working directory for validation without accessing any configured backend, use: Code Block $ tofu init -backend=false To verify configuration in the context of a particular run (a particular target workspace, input variable values, etc), use the `tofu plan` command instead, which includes an implied validation check. Usage[​](https://opentofu.org/docs/v1.10/cli/commands/validate/#usage "Direct link to Usage") ---------------------------------------------------------------------------------------------- Usage: `tofu validate [options]` This command accepts the following options: * `-json` - Produce output in a machine-readable JSON format, suitable for use in text editor integrations and other automated systems. Always disables color. * `-no-color` - If specified, output won't contain any color. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) for more information. JSON Output Format[​](https://opentofu.org/docs/v1.10/cli/commands/validate/#json-output-format "Direct link to JSON Output Format") ------------------------------------------------------------------------------------------------------------------------------------- When you use the `-json` option, OpenTofu will produce validation results in JSON format to allow using the validation result for tool integrations, such as highlighting errors in a text editor. As with all JSON output options, it's possible that OpenTofu will encounter an error prior to beginning the validation task that will thus not be subject to the JSON output setting. For that reason, external software consuming OpenTofu's output should be prepared to find data on stdout that _isn't_ valid JSON, which it should then treat as a generic error case. The output includes a `format_version` key, which has value `"1.0"`. The semantics of this version are: * We will increment the minor version, e.g. `"1.1"`, for backward-compatible changes or additions. Ignore any object properties with unrecognized names to remain forward-compatible with future minor versions. * We will increment the major version, e.g. `"2.0"`, for changes that are not backward-compatible. Reject any input which reports an unsupported major version. We will introduce new major versions only within the bounds of [the OpenTofu 1.0 Compatibility Promises](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/) . In the normal case, OpenTofu will print a JSON object to the standard output stream. The top-level JSON object will have the following properties: * `valid` (boolean): Summarizes the overall validation result, by indicating `true` if OpenTofu considers the current configuration to be valid or `false` if it detected any errors. * `error_count` (number): A zero or positive whole number giving the count of errors OpenTofu detected. If `valid` is `true` then `error_count` will always be zero, because it is the presence of errors that indicates that a configuration is invalid. * `warning_count` (number): A zero or positive whole number giving the count of warnings OpenTofu detected. Warnings do not cause OpenTofu to consider a configuration to be invalid, but they do indicate potential caveats that a user should consider and possibly resolve. * `diagnostics` (array of objects): A JSON array of nested objects that each describe an error or warning from OpenTofu. The nested objects in `diagnostics` have the following properties: * `severity` (string): A string keyword, either `"error"` or `"warning"`, indicating the diagnostic severity. The presence of errors causes OpenTofu to consider a configuration to be invalid, while warnings are just advice or caveats to the user which do not block working with the configuration. Later versions of OpenTofu may introduce new severity keywords, so consumers should be prepared to accept and ignore severity values they don't understand. * `summary` (string): A short description of the nature of the problem that the diagnostic is reporting. In OpenTofu's usual human-oriented diagnostic messages, the summary serves as a sort of "heading" for the diagnostic, printed after the "Error:" or "Warning:" indicator. Summaries are typically short, single sentences, but can sometimes be longer as a result of returning errors from subsystems that are not designed to return full diagnostics, where the entire error message therefore becomes the summary. In those cases, the summary might include newline characters which a renderer should honor when presenting the message visually to a user. * `detail` (string): An optional additional message giving more detail about the problem. In OpenTofu's usual human-oriented diagnostic messages, the detail provides the paragraphs of text that appear after the heading and the source location reference. Detail messages are often multiple paragraphs and possibly interspersed with non-paragraph lines, so tools which aim to present detail messages to the user should distinguish between lines without leading spaces, treating them as paragraphs, and lines with leading spaces, treating them as preformatted text. Renderers should then soft-wrap the paragraphs to fit the width of the rendering container, but leave the preformatted lines unwrapped. Some OpenTofu detail messages contain an approximation of bullet lists using ASCII characters to mark the bullets. This is not a contractural formatting convention, so renderers should avoid depending on it and should instead treat those lines as either paragraphs or preformatted text. Future versions of this format may define additional rules for other text conventions, but will maintain backward compatibility. * `range` (object): An optional object referencing a portion of the configuration source code that the diagnostic message relates to. For errors, this will typically indicate the bounds of the specific block header, attribute, or expression which was detected as invalid. A source range is an object with a property `filename` which gives the filename as a relative path from the current working directory, and then two properties `start` and `end` which are both themselves objects describing source positions, as described below. Not all diagnostic messages are connected with specific portions of the configuration, so `range` will be omitted or `null` for diagnostic messages where it isn't relevant. * `snippet` (object): An optional object including an excerpt of the configuration source code that the diagnostic message relates to. The snippet information includes: * `context` (string): An optional summary of the root context of the diagnostic. For example, this might be the resource block containing the expression which triggered the diagnostic. For some diagnostics this information is not available, and then this property will be `null`. * `code` (string): A snippet of OpenTofu configuration including the source of the diagnostic. This can be multiple lines and may include additional configuration source code around the expression which triggered the diagnostic. * `start_line` (number): A one-based line count representing the position in the source file at which the `code` excerpt begins. This is not necessarily the same value as `range.start.line`, as it is possible for `code` to include one or more lines of context before the source of the diagnostic. * `highlight_start_offset` (number): A zero-based character offset into the `code` string, pointing at the start of the expression which triggered the diagnostic. * `highlight_end_offset` (number): A zero-based character offset into the `code` string, pointing at the end of the expression which triggered the diagnostic. * `values` (array of objects): Contains zero or more expression values which may be useful in understanding the source of a diagnostic in a complex expression. These expression value objects are described below. ### Source Position[​](https://opentofu.org/docs/v1.10/cli/commands/validate/#source-position "Direct link to Source Position") A source position object, as used in the `range` property of a diagnostic object, has the following properties: * `byte` (number): A zero-based byte offset into the indicated file. * `line` (number): A one-based line count for the line containing the relevant position in the indicated file. * `column` (number): A one-based count of _Unicode characters_ from the start of the line indicated in `line`. A `start` position is inclusive while an `end` position is exclusive. The exact positions used for particular error messages are intended for human interpretation only. ### Expression Value[​](https://opentofu.org/docs/v1.10/cli/commands/validate/#expression-value "Direct link to Expression Value") An expression value object gives additional information about a value which is part of the expression which triggered the diagnostic. This is especially useful when using `for_each` or similar constructs, in order to identify exactly which values are responsible for an error. The object has two properties: * `traversal` (string): An HCL-like traversal string, such as `var.instance_count`. Complex index key values may be elided, so this will not always be valid, parseable HCL. The contents of this string are intended to be human-readable. * `statement` (string): A short English-language fragment describing the value of the expression when the diagnostic was triggered. The contents of this string are intended to be human-readable and are subject to change in future versions of OpenTofu. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/validate/#usage) * [JSON Output Format](https://opentofu.org/docs/v1.10/cli/commands/validate/#json-output-format) * [Source Position](https://opentofu.org/docs/v1.10/cli/commands/validate/#source-position) * [Expression Value](https://opentofu.org/docs/v1.10/cli/commands/validate/#expression-value) --- # Module Registry Protocol | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Module Registry Protocol ======================== The module registry protocol is what OpenTofu CLI uses to discover metadata about modules available for installation and to locate the distribution package for a selected module. The primary implementation of this protocol is the public [OpenTofu Registry](https://registry.opentofu.org/) at `registry.opentofu.org`. By writing and deploying your own implementation of this protocol, you can create a separate registry to distribute your own modules, as an alternative to publishing them on the public OpenTofu Registry. Module Addresses[​](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#module-addresses "Direct link to Module Addresses") -------------------------------------------------------------------------------------------------------------------------------------------- Each OpenTofu module has an associated address. A module address has the syntax `hostname/namespace/name/system`, where: * `hostname` is the hostname of the module registry that serves this module. * `namespace` is the name of a namespace, unique on a particular hostname, that can contain one or more modules that are somehow related. On the public OpenTofu Registry the "namespace" represents the organization that is packaging and distributing the module. * `name` is the module name, which generally names the abstraction that the module is intending to create. * `system` is the name of a remote system that the module is primarily written to target. For multi-cloud abstractions, there can be multiple modules with addresses that differ only in "system" to reflect provider-specific implementations of the abstraction, like `registry.opentofu.org/hashicorp/consul/aws` vs. `registry.opentofu.org/hashicorp/consul/azurerm`. The system name commonly matches the type portion of the address of an official provider, like `aws` or `azurerm` in the above examples, but that is not required and so you can use whichever system keywords make sense for the organization of your particular registry. The `hostname/` portion of a module address (including its slash delimiter) is optional, and if omitted defaults to `registry.opentofu.org/`. For example: * `hashicorp/consul/aws` is a shorthand for `registry.opentofu.org/hashicorp/consul/aws`, which is a module on the public registry for deploying Consul clusters in Amazon Web Services. * `example.com/awesomecorp/consul/happycloud` is a hypothetical module published on a third-party registry. If you intend to share a module you've developed for use by all OpenTofu users, please consider publishing it into the public [OpenTofu Registry](https://registry.opentofu.org/) to make your module more discoverable. You only need to implement this module registry protocol if you wish to publish modules whose addresses include a different hostname that is under your control. Module Versions[​](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#module-versions "Direct link to Module Versions") ----------------------------------------------------------------------------------------------------------------------------------------- Each distinct module address has associated with it a set of versions, each of which has an associated version number. OpenTofu assumes version numbers follow the [Semantic Versioning 2.0](https://semver.org/) conventions, with the user-facing behavior of the module serving as the "public API". Each `module` block may select a distinct version of a module, even if multiple blocks have the same source address. Service Discovery[​](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#service-discovery "Direct link to Service Discovery") ----------------------------------------------------------------------------------------------------------------------------------------------- The module registry protocol begins with OpenTofu CLI using [OpenTofu's remote service discovery protocol](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/) , with the hostname in the module address acting as the "User-facing Hostname". The service identifier for the module registry protocol is `modules.v1`. Its associated string value is the base URL for the relative URLs defined in the sections that follow. For example, the service discovery document for a host that _only_ implements the module registry protocol might contain the following: Code Block { "modules.v1": "/tofu/modules/v1/"} If the given URL is a relative URL then OpenTofu will interpret it as relative to the discovery document itself. The specific module registry protocol endpoints are defined as URLs relative to the given base URL, and so the specified base URL should generally end with a slash to ensure that those relative paths will be resolved as expected. The following sections describe the various operations that a module registry must implement to be compatible with OpenTofu CLI's module installer. The indicated URLs are all relative to the URL resulting from service discovery, as described above. We use a hypothetical URL for a provider registry, assuming that the caller already performed service discovery on a hypothetical `registry.example.io` to learn the base URL. The URLs are shown with the convention that a path portion with a colon `:` prefix is a placeholder for a dynamically-selected value, while all other path portions are literal. For example, in `:namespace/:type/versions`, the first two path portions are placeholders while the third is literally the string "versions". List Available Versions for a Specific Module[​](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#list-available-versions-for-a-specific-module "Direct link to List Available Versions for a Specific Module") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This is the primary endpoint for resolving module sources, returning the available versions for a given fully-qualified module. | Method | Path | Produces | | --- | --- | --- | | `GET` | `:namespace/:name/:system/versions` | `application/json` | ### Parameters[​](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#parameters "Direct link to Parameters") * `namespace` `(string: )` - The user or organization the module is owned by. This is required and is specified as part of the URL path. * `name` `(string: )` - The name of the module. This is required and is specified as part of the URL path. * `system` `(string: )` - The name of the target system. This is required and is specified as part of the URL path. ### Sample Request[​](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#sample-request "Direct link to Sample Request") Code Block $ curl 'https://registry.opentofu.org/v1/modules/hashicorp/consul/aws/versions' ### Sample Response[​](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#sample-response "Direct link to Sample Response") The `modules` array in the response always includes the requested module as the first element. OpenTofu does not use the other elements of this list. However, third-party implementations should always use a single-element list for forward compatibility. Each returned module has an array of available versions, which OpenTofu matches against any version constraints given in configuration. Code Block { "modules": [ { "versions": [ {"version": "1.0.0"}, {"version": "1.1.0"}, {"version": "2.0.0"} ] } ]} Return `404 Not Found` to indicate that no module is available with the requested namespace, name, and target system. Download Source Code for a Specific Module Version[​](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#download-source-code-for-a-specific-module-version "Direct link to Download Source Code for a Specific Module Version") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This endpoint downloads the specified version of a module for a single target system. | Method | Path | Produces | | --- | --- | --- | | `GET` | `:namespace/:name/:system/:version/download` | `application/json` | ### Parameters[​](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#parameters-1 "Direct link to Parameters") * `namespace` `(string: )` - The user the module is owned by. This is required and is specified as part of the URL path. * `name` `(string: )` - The name of the module. This is required and is specified as part of the URL path. * `system` `(string: )` - The name of the target system. This is required and is specified as part of the URL path. * `version` `(string: )` - The version of the module. This is required and is specified as part of the URL path. ### Sample Request[​](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#sample-request-1 "Direct link to Sample Request") Code Block $ curl -i 'https://registry.opentofu.org/v1/modules/foo/bar/baz/0.0.1/download' ### Sample Response[​](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#sample-response-1 "Direct link to Sample Response") A successful response contains the location from which the module version's source can be downloaded. It is expected to be found in the JSON encoded body as the value for the key `location`: Code Block HTTP/2 200Content-Length: 81{"location": "git::https://github.com/foo/terraform-baz-bar?ref=v0.0.1"} In the absence of a response body, OpenTofu will use the `X-Terraform-Get` header as the module location: Code Block HTTP/2 204 No ContentContent-Length: 0X-Terraform-Get: git::https://github.com/foo/terraform-baz-bar?ref=v0.0.1 Warning OpenTofu will prioritize reading the response body content if both, the body and the `X-Terraform-Get` header, are received from the registry server. The module location value accepts the same values as the `source` argument in a `module` block in OpenTofu configuration, as described in [Module Sources](https://opentofu.org/docs/v1.10/language/modules/sources/) , except that it may not recursively refer to another module registry address. The value of the module location may instead be a relative URL, indicated by beginning with `/`, `./` or `../`, in which case it is resolved relative to the full URL of the download endpoint to produce [an HTTP URL module source](https://opentofu.org/docs/v1.10/language/modules/sources/#http-urls) . * [Module Addresses](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#module-addresses) * [Module Versions](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#module-versions) * [Service Discovery](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#service-discovery) * [List Available Versions for a Specific Module](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#list-available-versions-for-a-specific-module) * [Parameters](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#parameters) * [Sample Request](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#sample-request) * [Sample Response](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#sample-response) * [Download Source Code for a Specific Module Version](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#download-source-code-for-a-specific-module-version) * [Parameters](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#parameters-1) * [Sample Request](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#sample-request-1) * [Sample Response](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/#sample-response-1) --- # Provider Registry Protocol | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provider Registry Protocol ========================== The provider registry protocol is what OpenTofu CLI uses to discover metadata about providers available for installation and to locate the distribution packages for a selected provider. The primary implementation of this protocol is the public [OpenTofu Registry](https://registry.opentofu.org/) at `registry.opentofu.org`. By writing and deploying your own implementation of this protocol, you can create a separate _origin registry_ to distribute your own providers, as an alternative to publishing them on the public OpenTofu Registry. This page describes the provider _registry_ protocol, which is the protocol for finding providers available for installation. It _doesn't_ describe the API that provider plugins themselves implement to serve requests from OpenTofu CLI at runtime. For more information on the provider API, see the OpenTofu SDK documentation. Provider Addresses[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#provider-addresses "Direct link to Provider Addresses") ---------------------------------------------------------------------------------------------------------------------------------------------------- Each OpenTofu provider has an associated address which uniquely identifies it within OpenTofu. A provider address has the syntax `hostname/namespace/type`, where: * `hostname` is the registry host that the provider is considered to have originated from, and the default location OpenTofu will consult for information about the provider [unless overridden in the CLI configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation) . * `namespace` is the name of a namespace, unique on a particular hostname, that can contain one or more providers that are somehow related. On the public OpenTofu Registry the "namespace" represents the organization that is packaging and distributing the provider. * `type` is the provider type, like "azurerm", "aws", "google", "dns", etc. A provider type is unique within a particular hostname and namespace. The `hostname/` portion of a provider address (including its slash delimiter) is optional, and if omitted defaults to `registry.opentofu.org/`. For example: * `hashicorp/aws` is a shorthand for `registry.opentofu.org/hashicorp/aws`, which is the official AWS provider published by HashiCorp. * `example/foo` is a shorthand for `registry.opentofu.org/example/foo`, which is a hypothetical third-party provider published on the public OpenTofu Registry. * `example.com/bar/baz` is a hypothetical third-party provider published at a third-party provider registry on `example.com`. If you intend only to share a provider you've developed for use by all OpenTofu users, please consider publishing it into the public [OpenTofu Registry](https://registry.opentofu.org/) , which will make your provider discoverable. You only need to implement this provider registry protocol if you wish to publish providers whose addresses include a different hostname that is under your control. OpenTofu uses the full address (after normalization to always include a hostname) as its global identifier for providers internally, and so it's important to note that re-uploading the `examplecorp/azurerm` provider into another namespace or publishing it on a different hostname will cause OpenTofu to see it as an entirely separate provider that will _not_ be usable by modules that declare a dependency on `examplecorp/azurerm`. If your goal is to create an alternative local distribution source for an existing provider -- that is, a _mirror_ of the provider -- refer to [the provider installation method configuration](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation) instead. Provider Versions[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#provider-versions "Direct link to Provider Versions") ------------------------------------------------------------------------------------------------------------------------------------------------- Each distinct provider address has associated with it a set of versions, each of which has an associated version number. OpenTofu assumes version numbers follow the [Semantic Versioning 2.0](https://semver.org/) conventions, with the schema and behavior of the provider as documented from the perspective of an end-user of OpenTofu serving as the "public API". All available versions for a particular provider address are considered to be the same provider by OpenTofu. Each OpenTofu configuration selects only one version of each provider for use in the entire configuration, so the version constraints across all modules are considered together for the purposes of version selection. Service Discovery[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#service-discovery "Direct link to Service Discovery") ------------------------------------------------------------------------------------------------------------------------------------------------- The providers protocol begins with OpenTofu CLI using [OpenTofu's remote service discovery protocol](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/) , with the hostname in the provider address acting as the "User-facing Hostname". The service identifier for the provider registry protocol is `providers.v1`. Its associated string value is the base URL for the relative URLs defined in the sections that follow. For example, the service discovery document for a host that _only_ implements the provider registry protocol might contain the following: Code Block { "providers.v1": "/tofu/providers/v1/"} If the given URL is a relative URL then OpenTofu will interpret it as relative to the discovery document itself. The specific provider registry protocol endpoints are defined as URLs relative to the given base URL, and so the specified base URL should generally end with a slash to ensure that those relative paths will be resolved as expected. The following sections describe the various operations that a provider registry must implement to be compatible with OpenTofu CLI's provider installer. The indicated URLs are all relative to the URL resulting from service discovery, as described above. We use a hypothetical URL for a provider registry, assuming that the caller already performed service discovery on a hypothetical `registry.example.io` to learn the base URL. The URLs are shown with the convention that a path portion with a colon `:` prefix is a placeholder for a dynamically-selected value, while all other path portions are literal. For example, in `:namespace/:type/versions`, the first two path portions are placeholders while the third is literally the string "versions". List Available Versions[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#list-available-versions "Direct link to List Available Versions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- This operation determines which versions are currently available for a particular provider. | Method | Path | Produces | | --- | --- | --- | | `GET` | `:namespace/:type/versions` | `application/json` | ### Parameters[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#parameters "Direct link to Parameters") * `namespace` (required): the namespace portion of the address of the requested provider. * `type` (required): the type portion of the address of the requested provider. ### Sample Request[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#sample-request "Direct link to Sample Request") Code Block curl 'https://registry.opentofu.org/v1/providers/examplecorp/random/versions' ### Sample Response[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#sample-response "Direct link to Sample Response") Code Block { "versions": [ { "version": "2.0.0", "protocols": ["4.0", "5.1"], "platforms": [ {"os": "darwin", "arch": "amd64"}, {"os": "linux", "arch": "amd64"}, {"os": "linux", "arch": "arm"}, {"os": "windows", "arch": "amd64"} ] }, { "version": "2.0.1", "protocols": ["5.2"], "platforms": [ {"os": "darwin", "arch": "amd64"}, {"os": "linux", "arch": "amd64"}, {"os": "linux", "arch": "arm"}, {"os": "windows", "arch": "amd64"} ] } ]} ### Response Properties[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#response-properties "Direct link to Response Properties") A successful result is a JSON object containing a single property `versions`. `versions` is an array of objects that each describe one available version, with the following properties: * `version` (required): the version number this object is describing, using the semantic versioning string notation. `version` must be unique across all objects in the response. * `protocols` (recommended): an array of OpenTofu provider API versions that this version supports, each given in `MAJOR.MINOR` format where each major version appears only once and the given minor version is the highest minor version supported. For example, `5.1` means that the provider supports both protocol `5.0` and protocol `5.1`. OpenTofu uses this information, when available, to provide hints to users about upgrading or downgrading their version of a particular provider to work with their current version of OpenTofu, if their currently-selected versions are not compatible. Which API versions are supported is, for most providers, decided by which version of the Terraform SDK they are built against. Consult the Terraform SDK documentation for more information. * `platforms` (recommended): an array of objects describing platforms that have packages available for this version. OpenTofu may use this information, when available, to provide hints to users about upgrading or downgrading their version of a particular provider for compatibility with their current platform. The `platforms` objects have properties `os` and `arch`, whose values match the properties of the same name in the response to [Find a Provider Package](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#find-a-provider-package) . Return `404 Not Found` to signal that the registry does not have a provider with the given namespace and type. Find a Provider Package[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#find-a-provider-package "Direct link to Find a Provider Package") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- This operation returns the download URL of and associated metadata about the distribution package for a particular version of a provider for a particular operating system and architecture. OpenTofu CLI uses this operation after it has selected the newest available version matching the configured version constraints, in order to find the zip archive containing the plugin itself. | Method | Path | Produces | | --- | --- | --- | | `GET` | `:namespace/:type/:version/download/:os/:arch` | `application/json` | ### Parameters[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#parameters-1 "Direct link to Parameters") * `namespace` (required): the namespace portion of the address of the requested provider. * `type` (required): the type portion of the address of the requested provider. * `version` (required): the version selected to download. This will exactly match one of the version strings returned from a previous call to [List Available Versions](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#list-available-versions) . * `os` (required): a keyword identifying the operating system that the returned package should be compatible with, like "linux" or "darwin". * `arch` (required): a keyword identifying the CPU architecture that the returned package should be compatible with, like "amd64" or "arm". ### Sample Request[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#sample-request-1 "Direct link to Sample Request") Code Block curl 'https://registry.opentofu.org/v1/providers/examplecorp/random/2.0.0/download/linux/amd64' ### Sample Response[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#sample-response-1 "Direct link to Sample Response") Code Block { "protocols": ["4.0", "5.1"], "os": "linux", "arch": "amd64", "filename": "terraform-provider-random_2.0.0_linux_amd64.zip", "download_url": "https://releases.example.com/terraform-provider-random/2.0.0/terraform-provider-random_2.0.0_linux_amd64.zip", "shasums_url": "https://releases.example.com/terraform-provider-random/2.0.0/terraform-provider-random_2.0.0_SHA256SUMS", "shasums_signature_url": "https://releases.example.com/terraform-provider-random/2.0.0/terraform-provider-random_2.0.0_SHA256SUMS.sig", "shasum": "5f9c7aa76b7c34d722fc9123208e26b22d60440cb47150dd04733b9b94f4541a", "signing_keys": { "gpg_public_keys": [ { "key_id": "51852D87348FFC4C", "ascii_armor": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1\n\nmQENBFMORM0BCADBRyKO1MhCirazOSVwcfTr1xUxjPvfxD3hjUwHtjsOy/bT6p9f\nW2mRPfwnq2JB5As+paL3UGDsSRDnK9KAxQb0NNF4+eVhr/EJ18s3wwXXDMjpIifq\nfIm2WyH3G+aRLTLPIpscUNKDyxFOUbsmgXAmJ46Re1fn8uKxKRHbfa39aeuEYWFA\n3drdL1WoUngvED7f+RnKBK2G6ZEpO+LDovQk19xGjiMTtPJrjMjZJ3QXqPvx5wca\nKSZLr4lMTuoTI/ZXyZy5bD4tShiZz6KcyX27cD70q2iRcEZ0poLKHyEIDAi3TM5k\nSwbbWBFd5RNPOR0qzrb/0p9ksKK48IIfH2FvABEBAAG0K0hhc2hpQ29ycCBTZWN1\ncml0eSA8c2VjdXJpdHlAaGFzaGljb3JwLmNvbT6JATgEEwECACIFAlMORM0CGwMG\nCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEFGFLYc0j/xMyWIIAIPhcVqiQ59n\nJc07gjUX0SWBJAxEG1lKxfzS4Xp+57h2xxTpdotGQ1fZwsihaIqow337YHQI3q0i\nSqV534Ms+j/tU7X8sq11xFJIeEVG8PASRCwmryUwghFKPlHETQ8jJ+Y8+1asRydi\npsP3B/5Mjhqv/uOK+Vy3zAyIpyDOMtIpOVfjSpCplVRdtSTFWBu9Em7j5I2HMn1w\nsJZnJgXKpybpibGiiTtmnFLOwibmprSu04rsnP4ncdC2XRD4wIjoyA+4PKgX3sCO\nklEzKryWYBmLkJOMDdo52LttP3279s7XrkLEE7ia0fXa2c12EQ0f0DQ1tGUvyVEW\nWmJVccm5bq25AQ0EUw5EzQEIANaPUY04/g7AmYkOMjaCZ6iTp9hB5Rsj/4ee/ln9\nwArzRO9+3eejLWh53FoN1rO+su7tiXJA5YAzVy6tuolrqjM8DBztPxdLBbEi4V+j\n2tK0dATdBQBHEh3OJApO2UBtcjaZBT31zrG9K55D+CrcgIVEHAKY8Cb4kLBkb5wM\nskn+DrASKU0BNIV1qRsxfiUdQHZfSqtp004nrql1lbFMLFEuiY8FZrkkQ9qduixo\nmTT6f34/oiY+Jam3zCK7RDN/OjuWheIPGj/Qbx9JuNiwgX6yRj7OE1tjUx6d8g9y\n0H1fmLJbb3WZZbuuGFnK6qrE3bGeY8+AWaJAZ37wpWh1p0cAEQEAAYkBHwQYAQIA\nCQUCUw5EzQIbDAAKCRBRhS2HNI/8TJntCAClU7TOO/X053eKF1jqNW4A1qpxctVc\nz8eTcY8Om5O4f6a/rfxfNFKn9Qyja/OG1xWNobETy7MiMXYjaa8uUx5iFy6kMVaP\n0BXJ59NLZjMARGw6lVTYDTIvzqqqwLxgliSDfSnqUhubGwvykANPO+93BBx89MRG\nunNoYGXtPlhNFrAsB1VR8+EyKLv2HQtGCPSFBhrjuzH3gxGibNDDdFQLxxuJWepJ\nEK1UbTS4ms0NgZ2Uknqn1WRU1Ki7rE4sTy68iZtWpKQXZEJa0IGnuI2sSINGcXCJ\noEIgXTMyCILo34Fa/C6VCm2WBgz9zZO8/rHIiQm1J5zqz0DrDwKBUM9C\n=LYpS\n-----END PGP PUBLIC KEY BLOCK-----", "trust_signature": "", "source": "ExampleCorp", "source_url": "https://www.examplecorp.com/security.html" } ] }} ### Response Properties[​](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#response-properties-1 "Direct link to Response Properties") A successful result is a JSON object with the following properties: * `protocols` (required): an array of OpenTofu provider API versions that the provider supports, in the same format as for [List Available Versions](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#list-available-versions) . While this property is optional when listing available options, it is _required_ for describing an individual provider package so that OpenTofu CLI can avoid downloading a package that will not be compatible with it. * `os` (required): this must echo back the `os` parameter from the request. * `arch` (required): this must echo back the `arch` parameter from the request. * `filename` (required): the filename for this provider's zip archive as recorded in the "shasums" document, so that OpenTofu CLI can determine which of the given checksums should be used for this specific package. * `download_url` (required): a URL from which OpenTofu can retrieve the provider's zip archive. If this is a relative URL then it will be resolved relative to the URL that returned the containing JSON object. * `shasums_url` (required): a URL from which OpenTofu can retrieve a text document recording expected SHA256 checksums for this package and possibly other packages for the same provider version on other platforms. The indicated document must be in the format generated by the `sha256` command available on many Unix systems, with one entry recording the same filename given in the `filename` property (case sensitive). * `shasums_signature_url` (required): a URL from which OpenTofu can retrieve a binary, detached GPG signature for the document at `shasums_url`, signed by one of the keys indicated in the `signing_keys` property. * `shasum` (required): the SHA256 checksum for this provider's zip archive as recorded in the shasums document. * `signing_keys` (required): an object describing signing keys for this provider package, one of which must have been used to produce the signature at `shasums_signature_url`. The object has the following nested properties: * `gpg_public_keys` (required): an array of objects, each describing one GPG signing key that is allowed to sign the checksums for this provider version. At least one element must be included, representing the key that produced the signature at `shasums_signature_url`. These objects have the following nested properties: * `key_id` (required): uppercase-hexadecimal-formatted ID for this GPG key * `ascii_armor` (required): an "ascii-armor" encoding of the **public key** associated with this GPG key. Return `404 Not Found` to signal that the given provider version isn't available for the requested operating system and/or architecture. OpenTofu CLI will only attempt to download versions that it has previously seen in response to [List Available Versions](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#list-available-versions) . * [Provider Addresses](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#provider-addresses) * [Provider Versions](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#provider-versions) * [Service Discovery](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#service-discovery) * [List Available Versions](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#list-available-versions) * [Parameters](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#parameters) * [Sample Request](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#sample-request) * [Sample Response](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#sample-response) * [Response Properties](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#response-properties) * [Find a Provider Package](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#find-a-provider-package) * [Parameters](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#parameters-1) * [Sample Request](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#sample-request-1) * [Sample Response](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#sample-response-1) * [Response Properties](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/#response-properties-1) --- # What are TACOS? | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/tacos/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) What are TACOS? =============== TF Automation and Collaboration Software (TACOS) are platforms which allow teams to manage and orchestrate OpenTofu execution. They offer a wide variety of services to provide a streamlined and collaborative experience. What are some examples? ======================= There are a variety of platforms which offer OpenTofu support, both Open Source and Commercial. Many of these organizations support OpenTofu directly and can be found on our [supporters](https://opentofu.org/supporters/) page. --- # Provider Network Mirror Protocol | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provider Network Mirror Protocol ================================ The provider network mirror protocol is an optional protocol which you can implement to provide an alternative installation source for Terraform providers, regardless of their origin registries. OpenTofu uses network mirrors only if you activate them explicitly in [the CLI configuration's `provider_installation` block](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation) . When enabled, a network mirror can serve providers belonging to any registry hostname, which can allow an organization to serve all of the OpenTofu providers they intend to use from an internal server, rather than from each provider's origin registry. This is _not_ the protocol that should be implemented by a host intending to serve as an origin registry for OpenTofu Providers. To provide an origin registry (whose hostname would then be included in the source addresses of the providers it hosts), implement [the provider registry protocol](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/) instead. Provider Addresses[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#provider-addresses "Direct link to Provider Addresses") ---------------------------------------------------------------------------------------------------------------------------------------------------------- Each OpenTofu provider has an associated address which uniquely identifies it within OpenTofu. A provider address has the syntax `hostname/namespace/type`, which is described in more detail in [the Provider Requirements documentation](https://opentofu.org/docs/v1.10/language/providers/requirements/) . By default, the `hostname` portion of a provider address serves both as part of its unique identifier _and_ as the location of the registry to retrieve it from. However, when you configure OpenTofu to install providers from a network mirror, the `hostname` serves _only_ as an identifier and no longer as an installation source. A provider mirror can therefore serve providers belonging to a variety of different provider registry hostnames, including providers from the public OpenTofu Registry at `registry.opentofu.org`, from a single server. In the relative URL patterns later in this document, the placeholder `:hostname` refers to the hostname from the address of the provider being requested, not the hostname where the provider network mirror is deployed. Protocol Base URL[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#protocol-base-url "Direct link to Protocol Base URL") ------------------------------------------------------------------------------------------------------------------------------------------------------- Most OpenTofu-native services use [the remote service discovery protocol](https://opentofu.org/docs/v1.10/internals/remote-service-discovery/) so that the physical location of the endpoints can potentially be separated from the hostname used in identifiers. The Provider Network Mirror protocol does _not_ use the service discovery indirection, because a network mirror location is only a physical location and is never used as part of the identifier of a dependency in a OpenTofu configuration. Instead, the provider installation section of the CLI configuration accepts a base URL directly. The given URL must use the scheme `https:`, and should end with a trailing slash so that the relative URLs of the individual operation endpoints will be resolved beneath it. Code Block provider_installation { network_mirror { url = "https://tofu.example.com/providers/" }} OpenTofu uses the base URL only as a stem to resolve the operation endpoint URLs against, and so it will never access the base URL directly. You can therefore, if desired, publish human-readable usage documentation for your network mirror at that URL. The following sections describe the various operations that a provider network mirror server must implement to be compatible with OpenTofu CLI's provider installer. The indicated URLs are all relative to the given base URL, as described above. The URLs are shown with the convention that a path portion with a colon `:` prefix is a placeholder for a dynamically-selected value, while all other path portions are literal. For example, in `:hostname/:namespace/:type/index.json`, the first three path portions are placeholders while the third is literally the string "index.json". The example requests in the following sections will assume the example mirror base URL from the above CLI configuration example. ### Authentication[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#authentication "Direct link to Authentication") If the CLI configuration includes [credentials](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials) for the hostname given in the network mirror base URL, OpenTofu will include those credentials in its requests for operations described below. If the given URL uses a non-standard port number (other than 443) then the credentials must be associated with a hostname that includes the port number, such as `tofu.example.com:8443`. OpenTofu does _not_ send credentials when retrieving the archives whose URLs are given in the "List Available Installation Packages" response below. If a particular mirror considers the distribution packages themselves to be sensitive then it must use cryptographically-secure, user-specific, and time-limited URLs in the metadata response. Strategies for doing so are out of scope of this protocol documentation. List Available Versions[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#list-available-versions "Direct link to List Available Versions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This operation determines which versions are currently available for a particular provider. | Method | Path | Produces | | --- | --- | --- | | `GET` | `:hostname/:namespace/:type/index.json` | `application/json` | ### Parameters[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#parameters "Direct link to Parameters") * `hostname` (required): the hostname portion of the address of the requested provider. * `namespace` (required): the namespace portion of the address of the requested provider. * `type` (required): the type portion of the address of the requested provider. ### Sample Request[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#sample-request "Direct link to Sample Request") Code Block curl 'https://tofu.example.com/providers/registry.tofu.io/hashicorp/random/index.json' ### Sample Response[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#sample-response "Direct link to Sample Response") Code Block { "versions": { "2.0.0": {}, "2.0.1": {} }} ### Response Properties[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#response-properties "Direct link to Response Properties") A successful result is a JSON object containing a single property `versions`, which must be a JSON object. Each of the property names of the `versions` object represents an available version number. The property values must be objects, but no properties are defined for those objects. We recommend leaving those objects empty for forward compatibility. Return `404 Not Found` to signal that the mirror does not have a provider with the given address. List Available Installation Packages[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#list-available-installation-packages "Direct link to List Available Installation Packages") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This operation returns download URLs and associated metadata for the distribution packages for a particular version of a provider. Each distribution package is associated with a particular operating system and architecture. A network mirror may host only a subset of the available packages for a provider version, if the users of the mirror are known to all use only a subset of the target platforms that OpenTofu supports. OpenTofu CLI uses this operation after it has selected the newest available version matching the configured version constraints, in order to find a zip archive containing the plugin itself. | Method | Path | Produces | | --- | --- | --- | | `GET` | `:hostname/:namespace/:type/:version.json` | `application/json` | ### Parameters[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#parameters-1 "Direct link to Parameters") * `hostname` (required): the hostname portion of the address of the requested provider. * `namespace` (required): the namespace portion of the address of the requested provider. * `type` (required): the type portion of the address of the requested provider. * `version` (required): the version selected to download. This will exactly match one of the version strings returned from a previous call to [List Available Versions](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#list-available-versions) . ### Sample Request[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#sample-request-1 "Direct link to Sample Request") Code Block curl 'https://tofu.example.com/providers/registry.tofu.io/hashicorp/random/2.0.0.json' ### Sample Response[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#sample-response-1 "Direct link to Sample Response") Code Block { "archives": { "darwin_amd64": { "url": "terraform-provider-random_2.0.0_darwin_amd64.zip", "hashes": [ "h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=" ] }, "linux_amd64": { "url": "terraform-provider-random_2.0.0_linux_amd64.zip", "hashes": [ "h1:lCJCxf/LIowc2IGS9TPjWDyXY4nOmdGdfcwwDQCOURQ=" ] } }} ### Response Properties[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#response-properties-1 "Direct link to Response Properties") A successful result is a JSON object with a property called `archives`, which must be a JSON object. Each of the property names of the `archives` object is a target platform identifier, which consists of an operating system and architecture concatenated with an underscore (`_`). Each property value in the `archives` object is itself a nested object with the following properties: * `url` (required): a string specifying the URL from which OpenTofu should download the `.zip` archive containing the requested provider plugin version. OpenTofu resolves the URL relative to the URL from which the current JSON document was returned, so the examples above containing only a filename would cause OpenTofu to construct a URL like: Code Block https://tofu.example.com/providers/registry.opentofu.org/hashicorp/random/terraform-provider-random_2.0.0_darwin_amd64.zip * `hashes` (optional): a JSON array of strings containing one or more hash values for the indicated archive. These hashes use OpenTofu's provider package hashing algorithm. At present, the easiest way to populate these is to construct a mirror's JSON indices using the `tofu providers mirror` command, as described in a later section, which will include the calculated hashes of each provider. If the response includes at least one hash, OpenTofu will select the hash whose algorithm it considers to be strongest and verify that the downloaded package matches that hash. If the response does not include a `hashes` property then OpenTofu will install the indicated archive with no verification. OpenTofu CLI will only attempt to download versions that it has previously seen in response to [List Available Versions](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#list-available-versions) . Provider Mirror as a Static Website[​](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#provider-mirror-as-a-static-website "Direct link to Provider Mirror as a Static Website") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The provider mirror protocol is designed so that it can potentially be implemented by placing files on typical static website hosting services. When using this strategy, implement the JSON index responses described above as `.json` files in the appropriate nested subdirectories, and ensure that your system is configured to serve `.json` files with the `application/json` media type. As a convenience, OpenTofu CLI includes [the `tofu providers mirror` subcommand](https://opentofu.org/docs/v1.10/cli/commands/providers/mirror/) , which will analyze the current configuration for the providers it requires, download the packages for those providers from their origin registries, and place them into a local directory suitable for use as a mirror. The `tofu providers mirror` subcommand also generates `index.json` and version-specific `.json` files that can, when placed in a static website hosting system, produce responses compatible with the provider mirror protocol. If you wish to create a mirror with providers for a number of different OpenTofu configurations, run `tofu providers mirror` in each configuration in turn while providing the same output directory each time. OpenTofu will then merge together all of the requirements into a single set of JSON indices. * [Provider Addresses](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#provider-addresses) * [Protocol Base URL](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#protocol-base-url) * [Authentication](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#authentication) * [List Available Versions](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#list-available-versions) * [Parameters](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#parameters) * [Sample Request](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#sample-request) * [Sample Response](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#sample-response) * [Response Properties](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#response-properties) * [List Available Installation Packages](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#list-available-installation-packages) * [Parameters](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#parameters-1) * [Sample Request](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#sample-request-1) * [Sample Response](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#sample-response-1) * [Response Properties](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#response-properties-1) * [Provider Mirror as a Static Website](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/#provider-mirror-as-a-static-website) --- # Installing OpenTofu on FreeBSD | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/install/bsd/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Installing OpenTofu on FreeBSD ============================== OpenTofu is available for FreeBSD and can be installed using the [pkg](https://pkgs.org/download/opentofu) and [port](https://cgit.freebsd.org/ports/commit/?id=f49b835b51fd5d92138706c32523c6f361740eac) system or by downloading the package directly. Installing using the pkg[​](https://opentofu.org/docs/v1.10/intro/install/bsd/#installing-using-the-pkg "Direct link to Installing using the pkg") --------------------------------------------------------------------------------------------------------------------------------------------------- Code Block pkg update -fpkg install opentofu Installing the port[​](https://opentofu.org/docs/v1.10/intro/install/bsd/#installing-the-port "Direct link to Installing the port") ------------------------------------------------------------------------------------------------------------------------------------ Code Block portsnap fetch extractmake -C /usr/ports/sysutils/opentofu install clean * [Installing using the pkg](https://opentofu.org/docs/v1.10/intro/install/bsd/#installing-using-the-pkg) * [Installing the port](https://opentofu.org/docs/v1.10/intro/install/bsd/#installing-the-port) --- # Use Cases | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/use-cases/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Use Cases ========= [OpenTofu](https://opentofu.org/docs/v1.10/) is an infrastructure as code tool that lets you define infrastructure resources in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to safely and efficiently provision and manage your infrastructure throughout its lifecycle. This page describes popular OpenTofu use cases and provides related resources that you can use to create OpenTofu configurations and workflows. Multi-Cloud Deployment[​](https://opentofu.org/docs/v1.10/intro/use-cases/#multi-cloud-deployment "Direct link to Multi-Cloud Deployment") ------------------------------------------------------------------------------------------------------------------------------------------- Provisioning infrastructure across multiple clouds increases fault-tolerance, allowing for more graceful recovery from cloud provider outages. However, multi-cloud deployments add complexity because each provider has its own interfaces, tools, and workflows. OpenTofu lets you use the same workflow to manage multiple providers and handle cross-cloud dependencies. This simplifies management and orchestration for large-scale, multi-cloud infrastructures. ### Resources[​](https://opentofu.org/docs/v1.10/intro/use-cases/#resources "Direct link to Resources") * Browse the [Public OpenTofu Registry](https://github.com/opentofu/registry/tree/main/providers) to find thousands of publicly available providers. Application Infrastructure Deployment, Scaling, and Monitoring Tools[​](https://opentofu.org/docs/v1.10/intro/use-cases/#application-infrastructure-deployment-scaling-and-monitoring-tools "Direct link to Application Infrastructure Deployment, Scaling, and Monitoring Tools") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can use OpenTofu to efficiently deploy, release, scale, and monitor infrastructure for multi-tier applications. N-tier application architecture lets you scale application components independently and provides a separation of concerns. An application could consist of a pool of web servers that use a database tier, with additional tiers for API servers, caching servers, and routing meshes. OpenTofu allows you to manage the resources in each tier together, and automatically handles dependencies between tiers. For example, OpenTofu will deploy a database tier before provisioning the web servers that depend on it. Self-Service Clusters[​](https://opentofu.org/docs/v1.10/intro/use-cases/#self-service-clusters "Direct link to Self-Service Clusters") ---------------------------------------------------------------------------------------------------------------------------------------- At a large organization, your centralized operations team may get many repetitive infrastructure requests. You can use OpenTofu to build a "self-serve" infrastructure model that lets product teams manage their own infrastructure independently. You can create and use OpenTofu modules that codify the standards for deploying and managing services in your organization, allowing teams to efficiently deploy services in compliance with your organization’s practices. A cloud backend can also integrate with ticketing systems like ServiceNow to automatically generate new infrastructure requests. Policy Compliance and Management[​](https://opentofu.org/docs/v1.10/intro/use-cases/#policy-compliance-and-management "Direct link to Policy Compliance and Management") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu can help you enforce policies on the types of resources teams can provision and use. Ticket-based review processes are a bottleneck that can slow down development. Instead, you can use Sentinel, a policy-as-code framework, to automatically enforce compliance and governance policies before OpenTofu makes infrastructure changes. Sentinel policies are available in cloud backends. PaaS Application Setup[​](https://opentofu.org/docs/v1.10/intro/use-cases/#paas-application-setup "Direct link to PaaS Application Setup") ------------------------------------------------------------------------------------------------------------------------------------------- Platform as a Service (PaaS) vendors like Heroku allow you to create web applications and attach add-ons, such as databases or email providers. Heroku can elastically scale the number of dynos or workers, but most non-trivial applications need many add-ons and external services. You can use OpenTofu to codify the setup required for a Heroku application, configure a DNSimple to set a CNAME, and set up Cloudflare as a Content Delivery Network (CDN) for the app. OpenTofu can quickly and consistently do all of this without a web interface. Software Defined Networking[​](https://opentofu.org/docs/v1.10/intro/use-cases/#software-defined-networking "Direct link to Software Defined Networking") ---------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu can interact with Software Defined Networks (SDNs) to automatically configure the network according to the needs of the applications running in it. This lets you move from a ticket-based workflow to an automated one, reducing deployment times. Kubernetes[​](https://opentofu.org/docs/v1.10/intro/use-cases/#kubernetes "Direct link to Kubernetes") ------------------------------------------------------------------------------------------------------- Kubernetes is an open-source workload scheduler for containerized applications. OpenTofu lets you both deploy a Kubernetes cluster and manage its resources (e.g., pods, deployments, services, etc.). Parallel Environments[​](https://opentofu.org/docs/v1.10/intro/use-cases/#parallel-environments "Direct link to Parallel Environments") ---------------------------------------------------------------------------------------------------------------------------------------- You may have staging or QA environments that you use to test new applications before releasing them in production. As the production environment grows larger and more complex, it can be increasingly difficult to maintain an up-to-date environment for each stage of the development process. OpenTofu lets you rapidly spin up and decommission infrastructure for development, test, QA, and production. Using OpenTofu to create disposable environments as needed is more cost-efficient than maintaining each one indefinitely. Software Demos[​](https://opentofu.org/docs/v1.10/intro/use-cases/#software-demos "Direct link to Software Demos") ------------------------------------------------------------------------------------------------------------------- You can use OpenTofu to create, provision, and bootstrap a demo on various cloud providers. This lets end users easily try the software on their own infrastructure and even enables them to adjust parameters like cluster size to more rigorously test tools at any scale. * [Multi-Cloud Deployment](https://opentofu.org/docs/v1.10/intro/use-cases/#multi-cloud-deployment) * [Resources](https://opentofu.org/docs/v1.10/intro/use-cases/#resources) * [Application Infrastructure Deployment, Scaling, and Monitoring Tools](https://opentofu.org/docs/v1.10/intro/use-cases/#application-infrastructure-deployment-scaling-and-monitoring-tools) * [Self-Service Clusters](https://opentofu.org/docs/v1.10/intro/use-cases/#self-service-clusters) * [Policy Compliance and Management](https://opentofu.org/docs/v1.10/intro/use-cases/#policy-compliance-and-management) * [PaaS Application Setup](https://opentofu.org/docs/v1.10/intro/use-cases/#paas-application-setup) * [Software Defined Networking](https://opentofu.org/docs/v1.10/intro/use-cases/#software-defined-networking) * [Kubernetes](https://opentofu.org/docs/v1.10/intro/use-cases/#kubernetes) * [Parallel Environments](https://opentofu.org/docs/v1.10/intro/use-cases/#parallel-environments) * [Software Demos](https://opentofu.org/docs/v1.10/intro/use-cases/#software-demos) --- # Installing OpenTofu on Alpine Linux | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/install/alpine/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Installing OpenTofu on Alpine Linux =================================== OpenTofu is available in the [Alpine Linux testing repository](https://pkgs.alpinelinux.org/packages?name=opentofu) or as an `.apk` package from the [GitHub releases page](https://github.com/opentofu/opentofu/releases/latest/) . Installing using the installer[​](https://opentofu.org/docs/v1.10/intro/install/alpine/#installing-using-the-installer "Direct link to Installing using the installer") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ You can use the OpenTofu installer script to run the installation. Code Block # Download the installer script:curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh -o install-opentofu.sh# Alternatively: wget --secure-protocol=TLSv1_2 --https-only https://get.opentofu.org/install-opentofu.sh -O install-opentofu.sh# Give it execution permissions:chmod +x install-opentofu.sh# Please inspect the downloaded script# Run the installer:./install-opentofu.sh --install-method apk# Remove the installer:rm -f install-opentofu.sh Installing the .apk[​](https://opentofu.org/docs/v1.10/intro/install/alpine/#installing-the-apk "Direct link to Installing the .apk") -------------------------------------------------------------------------------------------------------------------------------------- You can also [download the .apk](https://github.com/opentofu/opentofu/releases/latest/) and install it on your Alpine Linux. You can install the `.apk` package after downloading it: Code Block apk add --allow-untrusted tofu_*.apk Installing from the testing repository[​](https://opentofu.org/docs/v1.10/intro/install/alpine/#installing-from-the-testing-repository "Direct link to Installing from the testing repository") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ OpenTofu is currently available in the Alpine Testing repository and coming to Alpine stable. You can use the following commands to test Alpine installation. Code Block echo '@community https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositoriesapk add opentofu@community * [Installing using the installer](https://opentofu.org/docs/v1.10/intro/install/alpine/#installing-using-the-installer) * [Installing the .apk](https://opentofu.org/docs/v1.10/intro/install/alpine/#installing-the-apk) * [Installing from the testing repository](https://opentofu.org/docs/v1.10/intro/install/alpine/#installing-from-the-testing-repository) --- # Migration Guide | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Migration Guide =============== This guide walks you through migrating from Terraform to OpenTofu. It is designed to be safe and reversible, allowing you to test OpenTofu without disrupting your existing infrastructure. Prerequisites[​](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#prerequisites "Direct link to Prerequisites") -------------------------------------------------------------------------------------------------------------------------------- * An existing Terraform configuration * Access to your Terraform state files * Ability to run both `terraform` and `tofu` commands during the migration Step 1: Back up your infrastructure[​](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#step-1-back-up-your-infrastructure "Direct link to Step 1: Back up your infrastructure") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Before starting the migration, create backups of: 1. **Your Terraform state files** * For local state: Copy your `terraform.tfstate` and `terraform.tfstate_backup` files * For remote state: Follow your backend's backup procedures (e.g., S3 versioning, snapshot your state bucket) 2. **Your Terraform configuration files** * Commit all changes to version control * Consider creating a migration branch Step 2: Install OpenTofu[​](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#step-2-install-opentofu "Direct link to Step 2: Install OpenTofu") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Follow the [installation guide](https://opentofu.org/docs/intro/install/) to install OpenTofu on your system. Verify the installation: Code Block tofu --version Step 3: Initialize OpenTofu[​](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#step-3-initialize-opentofu "Direct link to Step 3: Initialize OpenTofu") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- In your Terraform project directory, initialize OpenTofu: Code Block tofu init This command will: * Download required providers from the OpenTofu registry * Initialize your backend configuration * Prepare your working directory Step 4: Verify your configuration[​](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#step-4-verify-your-configuration "Direct link to Step 4: Verify your configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Run a plan to ensure OpenTofu can read your state and configuration: Code Block tofu plan **Expected result**: You should see "No changes" or the same plan output you would see with Terraform. If you see unexpected changes: 1. Do not apply the changes 2. Investigate the differences 3. Consider rolling back (see below) Step 5: Apply with OpenTofu[​](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#step-5-apply-with-opentofu "Direct link to Step 5: Apply with OpenTofu") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Once you've verified the plan shows no unexpected changes, run: Code Block tofu apply Even if there are no infrastructure changes, this ensures OpenTofu updates the state file format if needed. Step 6: Test with a small change[​](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#step-6-test-with-a-small-change "Direct link to Step 6: Test with a small change") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Make a small, non-critical change to your configuration (e.g., add a tag to a resource) and run: Code Block tofu plantofu apply This verifies that OpenTofu can successfully manage your infrastructure going forward. Rolling back to Terraform[​](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#rolling-back-to-terraform "Direct link to Rolling back to Terraform") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you encounter issues during migration, you can safely roll back: 1. **Stop using OpenTofu immediately** 2. **Restore from your backups** (if any state changes were made) 3. **Run Terraform commands**: Code Block terraform initterraform plan 4. **Verify no unexpected changes** appear in the plan 5. **Continue using Terraform** as before Getting help[​](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#getting-help "Direct link to Getting help") ----------------------------------------------------------------------------------------------------------------------------- If you encounter issues during migration: * Join the [OpenTofu Slack](https://opentofu.org/slack/) * Ask on [GitHub Discussions](https://github.com/orgs/opentofu/discussions) * Report bugs on [GitHub Issues](https://github.com/opentofu/opentofu/issues) * [Prerequisites](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#prerequisites) * [Step 1: Back up your infrastructure](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#step-1-back-up-your-infrastructure) * [Step 2: Install OpenTofu](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#step-2-install-opentofu) * [Step 3: Initialize OpenTofu](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#step-3-initialize-opentofu) * [Step 4: Verify your configuration](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#step-4-verify-your-configuration) * [Step 5: Apply with OpenTofu](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#step-5-apply-with-opentofu) * [Step 6: Test with a small change](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#step-6-test-with-a-small-change) * [Rolling back to Terraform](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#rolling-back-to-terraform) * [Getting help](https://opentofu.org/docs/v1.10/intro/migration/migration-guide/#getting-help) --- # Installing OpenTofu via Homebrew | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/install/homebrew/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Installing OpenTofu via Homebrew ================================ You can use OpenTofu as a [standalone binary](https://opentofu.org/docs/v1.10/intro/install/standalone/) or you can install it using [Homebrew](https://formulae.brew.sh/formula/opentofu) . OpenTofu is available in the Homebrew Core repository, so you can install it by running: Code Block brew updatebrew install opentofu Validate the installation by running: Code Block tofu -version --- # Installing OpenTofu on Fedora | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/install/fedora/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Installing OpenTofu on Fedora ============================= OpenTofu is available in the [Fedora repository](https://src.fedoraproject.org/rpms/opentofu) as an `.rpm` package. Installing the .rpm package[​](https://opentofu.org/docs/v1.10/intro/install/fedora/#installing-the-rpm-package "Direct link to Installing the .rpm package") -------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block dnf install opentofu * [Installing the .rpm package](https://opentofu.org/docs/v1.10/intro/install/fedora/#installing-the-rpm-package) --- # Upgrading from OpenTofu 1.7.x/1.8.x/1.9.x | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/upgrading/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Upgrading from OpenTofu 1.7.x/1.8.x/1.9.x ========================================= OpenTofu 1.8.x is mostly compatible with previous OpenTofu versions (other than one minor breaking change in the S3 backend). This migration guide will take you through the process of upgrading OpenTofu to version 1.8.0. Step 0: Prepare a disaster recovery plan[​](https://opentofu.org/docs/v1.10/intro/upgrading/#step-0-prepare-a-disaster-recovery-plan "Direct link to Step 0: Prepare a disaster recovery plan") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Although OpenTofu 1.10 is mostly compatible with previous versions, you should take the necessary precautions to prevent accidents. Make sure you have an up to date and _tested_ disaster recovery plan. Step 1: If using an S3 backend - Remove any use of `use_legacy_workflow` from S3 backend configurations[​](https://opentofu.org/docs/v1.10/intro/upgrading/#step-1-if-using-an-s3-backend---remove-any-use-of-use_legacy_workflow-from-s3-backend-configurations "Direct link to step-1-if-using-an-s3-backend---remove-any-use-of-use_legacy_workflow-from-s3-backend-configurations") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you are using the S3 backend, with `use_legacy_workflow` set, you'd have to remove it. This field has been deprecated in version 1.7.0, and has been changed to default to `false`. The legacy workflow of authentication is no longer supported. Please start using the new authentication method, which is more consistent with other AWS tools Step 2: If you are using `ghcr.io/opentofu/opentofu` as a base image[​](https://opentofu.org/docs/v1.10/intro/upgrading/#step-2-if-you-are-using-ghcrioopentofuopentofu-as-a-base-image "Direct link to step-2-if-you-are-using-ghcrioopentofuopentofu-as-a-base-image") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you are using `ghcr.io/opentofu/opentofu` as a base image for your containers, you will need to move away from this setup. Please follow the instructions on the container installation page to build your own base image. Step 3: Apply all changes with OpenTofu 1.7.x/1.8.x/1.9.x[​](https://opentofu.org/docs/v1.10/intro/upgrading/#step-3-apply-all-changes-with-opentofu-17x18x19x "Direct link to Step 3: Apply all changes with OpenTofu 1.7.x/1.8.x/1.9.x") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Before proceeding, make sure that you apply all changes with `tofu apply`. Running `tofu plan` should result in no planned changes. While you can switch to OpenTofu with pending changes, it is not recommended. Code Block $ tofu plan...No changes. Your infrastructure matches the configuration.OpenTofu has compared your real infrastructure against yourconfiguration and found no differences, so no changes are needed. Step 4: Install OpenTofu 1.10.x[​](https://opentofu.org/docs/v1.10/intro/upgrading/#step-4-install-opentofu-110x "Direct link to Step 4: Install OpenTofu 1.10.x") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- As a first step, please [follow the installation instructions for the OpenTofu CLI tool](https://opentofu.org/docs/v1.10/intro/install/) . Please test if you can successfully execute the `tofu` command and receive the correct version: Code Block $ tofu --versionOpenTofu v1.10.0on linux_amd64 Step 5: Back up your state file[​](https://opentofu.org/docs/v1.10/intro/upgrading/#step-5-back-up-your-state-file "Direct link to Step 5: Back up your state file") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- Before you begin using the `tofu` binary on your Terraform code, make sure to back up your state file. If you are using a local state file, you can simply make a copy of your `terraform.tfstate` file in your project directory. If you are using a remote backend such as an S3 bucket, make sure that you follow the backup procedures for the backend and that you exercise the restore procedure at least once. Step 6: Initialize OpenTofu 1.10.x[​](https://opentofu.org/docs/v1.10/intro/upgrading/#step-6-initialize-opentofu-110x "Direct link to Step 6: Initialize OpenTofu 1.10.x") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Warning Should any of the following steps fail, please do not proceed and follow the [rollback instructions below](https://opentofu.org/docs/v1.10/intro/upgrading/#rolling-back-and-reporting-issues) instead. If you suspect the failure may be the result of a bug in OpenTofu, [please help us by opening an issue](https://github.com/opentofu/opentofu/issues) . Now you are ready to migrate. Run `tofu init` in the directory where your code resides. OpenTofu will download any providers and modules referenced in your configuration from the OpenTofu registry. Note If you are using the S3 backend - You will need to run `tofu init -reconfigure` to reinitialize the backend. Step 7: Inspect the plan[​](https://opentofu.org/docs/v1.10/intro/upgrading/#step-7-inspect-the-plan "Direct link to Step 7: Inspect the plan") ------------------------------------------------------------------------------------------------------------------------------------------------ Once initialized, run `tofu plan` and ensure that there are no pending changes similar to step 1 above. If there are unexpected changes in the plan, roll back to OpenTofu 1.6.x/1.7.x and troubleshoot your migration. (See the Troubleshooting section below.) Code Block $ tofu plan...No changes. Your infrastructure matches the configuration.OpenTofu has compared your real infrastructure against yourconfiguration and found no differences, so no changes are needed. Step 8: Test out a small change[​](https://opentofu.org/docs/v1.10/intro/upgrading/#step-8-test-out-a-small-change "Direct link to Step 8: Test out a small change") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- Before you begin using OpenTofu for larger changes, test out `tofu apply` with a smaller, non-critical change. Rolling back and reporting issues[​](https://opentofu.org/docs/v1.10/intro/upgrading/#rolling-back-and-reporting-issues "Direct link to Rolling back and reporting issues") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you have issues migrating to OpenTofu you can follow these steps to roll back to OpenTofu 1.7.x/1.8.x/1.9.x: 1. Create another backup of your state file. 2. Remove OpenTofu 1.10.x and verify that you are running OpenTofu 1.7.x/1.8.x/1.9.x. 3. Run `tofu init`. 4. Run `tofu plan` and verify that no unexpected changes are in the plan. 5. Test the rollback with a small, non-critical change. If you encountered a bug, [please report it on GitHub](https://github.com/opentofu/opentofu/issues) . Troubleshooting[​](https://opentofu.org/docs/v1.10/intro/upgrading/#troubleshooting "Direct link to Troubleshooting") ---------------------------------------------------------------------------------------------------------------------- If you encounter any issues during the migration to OpenTofu, you can join the [OpenTofu Slack](https://opentofu.org/slack/) or ask on [GitHub Discussions](https://github.com/orgs/opentofu/discussions) . ### Error: Failed to query available provider packages[​](https://opentofu.org/docs/v1.10/intro/upgrading/#error-failed-to-query-available-provider-packages "Direct link to Error: Failed to query available provider packages") This error happens when a provider you specified in your configuration is not available in the OpenTofu registry. Please roll back to OpenTofu 1.7.x/1.8.x/1.9.x and make sure your code works with that version. If your code works, please [submit an issue to include the provider in the registry](https://github.com/opentofu/registry/issues/) . ### Error: Module not found[​](https://opentofu.org/docs/v1.10/intro/upgrading/#error-module-not-found "Direct link to Error: Module not found") This error happens when a module you specified in your configuration is not available in the OpenTofu registry. Please roll back to OpenTofu 1.7.x/1.8.x/1.9.x and make sure your code works with that version. If your code works, please [submit an issue to include the module in the registry](https://github.com/opentofu/registry/issues/) . * [Step 0: Prepare a disaster recovery plan](https://opentofu.org/docs/v1.10/intro/upgrading/#step-0-prepare-a-disaster-recovery-plan) * [Step 1: If using an S3 backend - Remove any use of `use_legacy_workflow` from S3 backend configurations](https://opentofu.org/docs/v1.10/intro/upgrading/#step-1-if-using-an-s3-backend---remove-any-use-of-use_legacy_workflow-from-s3-backend-configurations) * [Step 2: If you are using `ghcr.io/opentofu/opentofu` as a base image](https://opentofu.org/docs/v1.10/intro/upgrading/#step-2-if-you-are-using-ghcrioopentofuopentofu-as-a-base-image) * [Step 3: Apply all changes with OpenTofu 1.7.x/1.8.x/1.9.x](https://opentofu.org/docs/v1.10/intro/upgrading/#step-3-apply-all-changes-with-opentofu-17x18x19x) * [Step 4: Install OpenTofu 1.10.x](https://opentofu.org/docs/v1.10/intro/upgrading/#step-4-install-opentofu-110x) * [Step 5: Back up your state file](https://opentofu.org/docs/v1.10/intro/upgrading/#step-5-back-up-your-state-file) * [Step 6: Initialize OpenTofu 1.10.x](https://opentofu.org/docs/v1.10/intro/upgrading/#step-6-initialize-opentofu-110x) * [Step 7: Inspect the plan](https://opentofu.org/docs/v1.10/intro/upgrading/#step-7-inspect-the-plan) * [Step 8: Test out a small change](https://opentofu.org/docs/v1.10/intro/upgrading/#step-8-test-out-a-small-change) * [Rolling back and reporting issues](https://opentofu.org/docs/v1.10/intro/upgrading/#rolling-back-and-reporting-issues) * [Troubleshooting](https://opentofu.org/docs/v1.10/intro/upgrading/#troubleshooting) * [Error: Failed to query available provider packages](https://opentofu.org/docs/v1.10/intro/upgrading/#error-failed-to-query-available-provider-packages) * [Error: Module not found](https://opentofu.org/docs/v1.10/intro/upgrading/#error-module-not-found) --- # Installing OpenTofu via Snapcraft (Linux) | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/install/snap/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Installing OpenTofu via Snapcraft (Linux) ========================================= OpenTofu is available on [Snapcraft](https://snapcraft.io/) and you can install it by running: Code Block snap install --classic opentofu Snap is available by default on Ubuntu Linux and [can be installed on other Linux distributions, too](https://snapcraft.io/docs/installing-snapd) . --- # Installing OpenTofu | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/install/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Installing OpenTofu =================== You can install OpenTofu via a wide range of methods. Please select your operating system and installation method: [Alpine Linux (.apk)](https://opentofu.org/docs/v1.10/intro/install/alpine/) ----------------------------------------------------------------------------- Install OpenTofu from an .apk package directly. [Debian Linux and derivatives (.deb)](https://opentofu.org/docs/v1.10/intro/install/deb/) ------------------------------------------------------------------------------------------ Install OpenTofu on Debian, Ubuntu, or any other .deb-based Linux distribution using your package manager. [FreeBSD](https://opentofu.org/docs/v1.10/intro/install/bsd/) -------------------------------------------------------------- Use OpenTofu without installation on FreeBSD. [Fedora](https://opentofu.org/docs/v1.10/intro/install/fedora/) ---------------------------------------------------------------- Installing OpenTofu on Fedora. [RHEL and derivatives (.rpm)](https://opentofu.org/docs/v1.10/intro/install/rpm/) ---------------------------------------------------------------------------------- Install OpenTofu on RHEL, openSUSE, AlmaLinux, or any other .rpm-based Linux distribution using your package manager. [Ubuntu Linux (Snap)](https://opentofu.org/docs/v1.10/intro/install/snap/) --------------------------------------------------------------------------- Install OpenTofu on Ubuntu, Manjaro, or any other Linux distribution using Snap. [MacOS or Linux (Homebrew)](https://opentofu.org/docs/v1.10/intro/install/homebrew/) ------------------------------------------------------------------------------------- Install OpenTofu on MacOS or Linux using Homebrew. [Windows](https://opentofu.org/docs/v1.10/intro/install/windows/) ------------------------------------------------------------------ Install OpenTofu on Windows. [OCI container image](https://opentofu.org/docs/v1.10/intro/install/docker/) ----------------------------------------------------------------------------- Use official OCI container image available on GitHub Container Registry. [Standalone (Linux/MacOS/Windows/BSD)](https://opentofu.org/docs/v1.10/intro/install/standalone/) -------------------------------------------------------------------------------------------------- Use OpenTofu without installation on Linux, MacOS, Windows or FreeBSD. --- # OpenTofu vs. Alternatives | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/vs/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu vs. Alternatives ========================= OpenTofu provides a flexible abstraction of resources and providers. This model allows for representing everything from physical hardware, virtual machines, and containers, to email and DNS providers. Because of this flexibility, OpenTofu can be used to solve many different problems. This means there are a number of existing tools that overlap with the capabilities of OpenTofu. We compare OpenTofu to a number of these tools, but it should be noted that OpenTofu is not mutually exclusive with other systems. It can be used to manage a single application, or the entire datacenter. Learn how OpenTofu compares to: * [Chef, Puppet, etc.](https://opentofu.org/docs/v1.10/intro/vs/chef-puppet/) * [CloudFormation, Heat, etc.](https://opentofu.org/docs/v1.10/intro/vs/cloudformation/) * [Custom Solutions](https://opentofu.org/docs/v1.10/intro/vs/custom/) * [Boto, Fog, etc.](https://opentofu.org/docs/v1.10/intro/vs/boto/) * [Terraform](https://opentofu.org/faq/#opentofu-terraform-differences) --- # OpenTofu vs. Boto, Fog, etc. | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/vs/boto/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu vs. Boto, Fog, etc. ============================ Libraries like Boto, Fog, etc. are used to provide native access to cloud providers and services by using their APIs. Some libraries are focused on specific clouds, while others attempt to bridge them all and mask the semantic differences. Using a client library only provides low-level access to APIs, requiring application developers to create their own tooling to build and manage their infrastructure. OpenTofu is not intended to give low-level programmatic access to providers, but instead provides a high level syntax for describing how cloud resources and services should be created, provisioned, and combined. OpenTofu is very flexible, using a plugin-based model to support providers and provisioners, giving it the ability to support almost any service that exposes APIs. --- # OpenTofu vs. CloudFormation, Heat, etc. | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/vs/cloudformation/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu vs. CloudFormation, Heat, etc. ======================================= Tools like CloudFormation, Heat, etc. allow the details of an infrastructure to be codified into a configuration file. The configuration files allow the infrastructure to be elastically created, modified and destroyed. OpenTofu is inspired by the problems they solve. OpenTofu similarly uses configuration files to detail the infrastructure setup, but it goes further by being both cloud-agnostic and enabling multiple providers and services to be combined and composed. For example, OpenTofu can be used to orchestrate an AWS and OpenStack cluster simultaneously, while enabling 3rd-party providers like Cloudflare and DNSimple to be integrated to provide CDN and DNS services. This enables OpenTofu to represent and manage the entire infrastructure with its supporting services, instead of only the subset that exists within a single provider. It provides a single unified syntax, instead of requiring operators to use independent and non-interoperable tools for each platform and service. OpenTofu also separates the planning phase from the execution phase, by using the concept of an execution plan. By running `tofu plan`, the current state is refreshed and the configuration is consulted to generate an action plan. The plan includes all actions to be taken: which resources will be created, destroyed or modified. It can be inspected by operators to ensure it is exactly what is expected. Using `tofu graph`, the plan can be visualized to show dependent ordering. Once the plan is captured, the execution phase can be limited to only the actions in the plan. Other tools combine the planning and execution phases, meaning operators are forced to mentally reason about the effects of a change, which quickly becomes intractable in large infrastructures. OpenTofu lets operators apply changes with confidence, as they know exactly what will happen beforehand. --- # OpenTofu vs. Chef, Puppet, etc. | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/vs/chef-puppet/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu vs. Chef, Puppet, etc. =============================== Configuration management tools install and manage software on a machine that already exists. OpenTofu is not a configuration management tool, and it allows existing tooling to focus on their strengths: bootstrapping and initializing resources. OpenTofu focuses on the higher-level abstraction of the datacenter and associated services, while allowing you to use configuration management tools on individual systems. It also aims to bring the same benefits of codification of your system configuration to infrastructure management. If you are using traditional configuration management within your compute instances, you can use OpenTofu to configure bootstrapping software like cloud-init to activate your configuration management software on first system boot. --- # Installing OpenTofu from GitHub Releases | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/install/windows/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Installing OpenTofu from GitHub Releases ======================================== * winget * scoop OpenTofu is available on [the winget repository](https://github.com/microsoft/winget-pkgs/tree/master/manifests/o/OpenTofu/Tofu/) and you can install it by running: Code Block winget install --exact --id=OpenTofu.Tofu Verify installation: Code Block tofu -version Note If you run into issues when installing with winget, please make sure that `%LOCALAPPDATA%\Microsoft\WinGet\Links` is in your PATH environment variable. OpenTofu is available on [the scoop repository](https://github.com/ScoopInstaller/Main/blob/master/bucket/opentofu.json) and you can install it by running: Code Block scoop bucket add mainscoop install main/opentofu Verify installation: Code Block tofu -version --- # Building a Docker Image with OpenTofu | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/install/docker/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Building a Docker Image with OpenTofu ===================================== Important Change Previously, OpenTofu provided official Docker images that could be used directly. Starting with OpenTofu 1.10, direct usage of the official images is no longer supported. This page now focuses on how to build your own Docker image with OpenTofu included. If you were previously using `docker run ghcr.io/opentofu/opentofu`, you will need to build your own image following the instructions below. Building your own image[​](https://opentofu.org/docs/v1.10/intro/install/docker/#building-your-own-image "Direct link to Building your own image") --------------------------------------------------------------------------------------------------------------------------------------------------- If you need OpenTofu in a Docker container, you will need to build your own image. You can do this in two ways: 1. Use a multi-stage build to copy the `tofu` binary from the minimal OpenTofu image to your image. 2. Use the standalone installation script to install `tofu` into your container image. ### Method 1: Using a multi-stage build[​](https://opentofu.org/docs/v1.10/intro/install/docker/#method-1-using-a-multi-stage-build "Direct link to Method 1: Using a multi-stage build") The minimal OpenTofu images contain only the `tofu` binary at `/usr/local/bin/tofu`. You can use these images in a multi-stage build to copy the binary into your own image. Available minimal image tags: * `ghcr.io/opentofu/opentofu:minimal` - Latest version * `ghcr.io/opentofu/opentofu:1-minimal` - Latest 1.x version * `ghcr.io/opentofu/opentofu:1.9-minimal` - Latest 1.9.x version * `ghcr.io/opentofu/opentofu:1.9.1-minimal` - Specific version Example `Dockerfile` using Alpine Linux: Code Block FROM ghcr.io/opentofu/opentofu:minimal AS tofuFROM alpine:3.20# Copy the tofu binary from the minimal imageCOPY --from=tofu /usr/local/bin/tofu /usr/local/bin/tofu# Add any other tools or dependencies you needRUN apk add --no-cache git curl# Your application setupWORKDIR /workspace Example using Ubuntu: Code Block FROM ghcr.io/opentofu/opentofu:minimal AS tofuFROM ubuntu:24.04# Copy the tofu binaryCOPY --from=tofu /usr/local/bin/tofu /usr/local/bin/tofu# Install dependenciesRUN apt-get update && apt-get install -y \ git \ curl \ && rm -rf /var/lib/apt/lists/*WORKDIR /workspace ### Method 2: Using the installation script[​](https://opentofu.org/docs/v1.10/intro/install/docker/#method-2-using-the-installation-script "Direct link to Method 2: Using the installation script") You can also use the OpenTofu installation script to install the binary directly in your container image. #### Step 1: Download the installation script[​](https://opentofu.org/docs/v1.10/intro/install/docker/#step-1-download-the-installation-script "Direct link to Step 1: Download the installation script") First, download the installation script following the [standalone installation instructions](https://opentofu.org/docs/v1.10/intro/install/standalone/) and place it next to your `Dockerfile`. #### Step 2: Install OpenTofu in your image[​](https://opentofu.org/docs/v1.10/intro/install/docker/#step-2-install-opentofu-in-your-image "Direct link to Step 2: Install OpenTofu in your image") Example `Dockerfile` using the installation script: Code Block FROM alpine:3.20# Copy the installation scriptCOPY install-opentofu.sh /tmp/install-opentofu.sh# Install dependencies needed for the scriptRUN apk add --no-cache bash curl gpg gpg-agent# Run the installation scriptRUN chmod +x /tmp/install-opentofu.sh && \ /tmp/install-opentofu.sh --install-method standalone --install-path /usr/local/bin && \ rm /tmp/install-opentofu.sh# Add your other dependenciesRUN apk add --no-cache gitWORKDIR /workspace For Ubuntu-based images: Code Block FROM ubuntu:24.04# Copy the installation scriptCOPY install-opentofu.sh /tmp/install-opentofu.sh# Install dependenciesRUN apt-get update && apt-get install -y \ curl \ gpg \ && rm -rf /var/lib/apt/lists/*# Run the installation scriptRUN chmod +x /tmp/install-opentofu.sh && \ /tmp/install-opentofu.sh --install-method standalone --install-path /usr/local/bin && \ rm /tmp/install-opentofu.sh# Add your other dependenciesRUN apt-get update && apt-get install -y \ git \ && rm -rf /var/lib/apt/lists/*WORKDIR /workspace Verifying your image[​](https://opentofu.org/docs/v1.10/intro/install/docker/#verifying-your-image "Direct link to Verifying your image") ------------------------------------------------------------------------------------------------------------------------------------------ After building your image, verify that OpenTofu is correctly installed: Code Block docker build -t my-opentofu-image .docker run --rm my-opentofu-image tofu --version * [Building your own image](https://opentofu.org/docs/v1.10/intro/install/docker/#building-your-own-image) * [Method 1: Using a multi-stage build](https://opentofu.org/docs/v1.10/intro/install/docker/#method-1-using-a-multi-stage-build) * [Method 2: Using the installation script](https://opentofu.org/docs/v1.10/intro/install/docker/#method-2-using-the-installation-script) * [Verifying your image](https://opentofu.org/docs/v1.10/intro/install/docker/#verifying-your-image) --- # Installing OpenTofu on .deb-based Linux (Debian, Ubuntu, etc.) | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/install/deb/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Installing OpenTofu on .deb-based Linux (Debian, Ubuntu, etc.) ============================================================== [Thank you to Buildkite for sponsoring the OpenTofu package hosting.](https://buildkite.com/) You can install OpenTofu from our Debian repository by following the step-by-step instructions below. Installing using the installer[​](https://opentofu.org/docs/v1.10/intro/install/deb/#installing-using-the-installer "Direct link to Installing using the installer") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can use the OpenTofu installer script to run the installation. Code Block # Download the installer script:curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh -o install-opentofu.sh# Alternatively: wget --secure-protocol=TLSv1_2 --https-only https://get.opentofu.org/install-opentofu.sh -O install-opentofu.sh# Give it execution permissions:chmod +x install-opentofu.sh# Please inspect the downloaded script# Run the installer:./install-opentofu.sh --install-method deb# Remove the installer:rm -f install-opentofu.sh Step-by-step instructions[​](https://opentofu.org/docs/v1.10/intro/install/deb/#step-by-step-instructions "Direct link to Step-by-step instructions") ------------------------------------------------------------------------------------------------------------------------------------------------------ The following steps explain how to set up the OpenTofu Debian repositories. These instructions should work on most Debian-based Linux systems. ### Installing tooling[​](https://opentofu.org/docs/v1.10/intro/install/deb/#installing-tooling "Direct link to Installing tooling") In order to add the repositories, you will need to install some tooling. On most Debian-based operating systems, these tools will already be installed. Code Block sudo apt-get updatesudo apt-get install -y apt-transport-https ca-certificates curl gnupg ### Set up the OpenTofu repository[​](https://opentofu.org/docs/v1.10/intro/install/deb/#set-up-the-opentofu-repository "Direct link to Set up the OpenTofu repository") First, you need to make sure you have a copy of the OpenTofu GPG key. This verifies that your packages have indeed been created using the official pipeline and have not been tampered with. Code Block sudo install -m 0755 -d /etc/apt/keyringscurl -fsSL https://get.opentofu.org/opentofu.gpg | sudo tee /etc/apt/keyrings/opentofu.gpg >/dev/nullcurl -fsSL https://packages.opentofu.org/opentofu/tofu/gpgkey | sudo gpg --no-tty --batch --dearmor -o /etc/apt/keyrings/opentofu-repo.gpg >/dev/nullsudo chmod a+r /etc/apt/keyrings/opentofu.gpg /etc/apt/keyrings/opentofu-repo.gpg Now you have to create the OpenTofu source list. Code Block echo \ "deb [signed-by=/etc/apt/keyrings/opentofu.gpg,/etc/apt/keyrings/opentofu-repo.gpg] https://packages.opentofu.org/opentofu/tofu/any/ any maindeb-src [signed-by=/etc/apt/keyrings/opentofu.gpg,/etc/apt/keyrings/opentofu-repo.gpg] https://packages.opentofu.org/opentofu/tofu/any/ any main" | \ sudo tee /etc/apt/sources.list.d/opentofu.list > /dev/nullsudo chmod a+r /etc/apt/sources.list.d/opentofu.list ### Installing OpenTofu[​](https://opentofu.org/docs/v1.10/intro/install/deb/#installing-opentofu "Direct link to Installing OpenTofu") Finally, you can install OpenTofu: Code Block sudo apt-get updatesudo apt-get install -y tofu * [Installing using the installer](https://opentofu.org/docs/v1.10/intro/install/deb/#installing-using-the-installer) * [Step-by-step instructions](https://opentofu.org/docs/v1.10/intro/install/deb/#step-by-step-instructions) * [Installing tooling](https://opentofu.org/docs/v1.10/intro/install/deb/#installing-tooling) * [Set up the OpenTofu repository](https://opentofu.org/docs/v1.10/intro/install/deb/#set-up-the-opentofu-repository) * [Installing OpenTofu](https://opentofu.org/docs/v1.10/intro/install/deb/#installing-opentofu) --- # Machine-Readable UI | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Machine-Readable UI =================== By default, many OpenTofu commands display UI output as unstructured text, intended to be read by a user via a terminal emulator. This text stream is not a stable interface for integrations. Some commands support a `-json` flag, which enables a structured JSON output mode with a defined interface. For long-running commands such as `plan`, `apply`, and `refresh` the `-json` flag outputs a stream of JSON UI messages, one per line. These can be processed one message at a time, with integrating software filtering, combining, or modifying the output as desired. The first message output has type `version`, and includes a `ui` key, which has value `"1.0"`. The semantics of this version are: * We will increment the minor version, e.g. `"1.1"`, for backward-compatible changes or additions. Ignore any object properties with unrecognized names to remain forward-compatible with future minor versions. * We will increment the major version, e.g. `"2.0"`, for changes that are not backward-compatible. Reject any input which reports an unsupported major version. We will introduce new major versions only within the bounds of [the OpenTofu 1.0 Compatibility Promises](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/) . Sample JSON Output[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#sample-json-output "Direct link to Sample JSON Output") --------------------------------------------------------------------------------------------------------------------------------------------- Below is sample output from running `tofu apply -json`: Code Block {"@level":"info","@message":"OpenTofu 1.6.0","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.275359-04:00","tofu":"0.15.4","type":"version","ui":"0.1.0"}{"@level":"info","@message":"random_pet.animal: Plan to create","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.705503-04:00","change":{"resource":{"addr":"random_pet.animal","module":"","resource":"random_pet.animal","implied_provider":"random","resource_type":"random_pet","resource_name":"animal","resource_key":null},"action":"create"},"type":"planned_change"}{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.705638-04:00","changes":{"add":1,"change":0,"remove":0,"operation":"plan"},"type":"change_summary"}{"@level":"info","@message":"random_pet.animal: Creating...","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.825308-04:00","hook":{"resource":{"addr":"random_pet.animal","module":"","resource":"random_pet.animal","implied_provider":"random","resource_type":"random_pet","resource_name":"animal","resource_key":null},"action":"create"},"type":"apply_start"}{"@level":"info","@message":"random_pet.animal: Creation complete after 0s [id=smart-lizard]","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.826179-04:00","hook":{"resource":{"addr":"random_pet.animal","module":"","resource":"random_pet.animal","implied_provider":"random","resource_type":"random_pet","resource_name":"animal","resource_key":null},"action":"create","id_key":"id","id_value":"smart-lizard","elapsed_seconds":0},"type":"apply_complete"}{"@level":"info","@message":"Apply complete! Resources: 1 added, 0 changed, 0 destroyed.","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.869168-04:00","changes":{"add":1,"change":0,"remove":0,"operation":"apply"},"type":"change_summary"}{"@level":"info","@message":"Outputs: 1","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.869280-04:00","outputs":{"pets":{"sensitive":false,"type":"string","value":"smart-lizard"}},"type":"outputs"} Each line consists of a JSON object with several keys common to all messages. These are: * `@level`: this is normally "info", but can be "error" or "warn" when showing diagnostics * `@message`: a human-readable summary of the contents of this message * `@module`: always "tofu.ui" when rendering UI output * `@timestamp`: an RFC3339 timestamp of when the message was output * `type`: defines which kind of message this is and determines how to interpret other keys which may be present Clients presenting the logs as a user interface should handle unexpected message types by presenting at least the `@message` field to the user. Messages will be emitted as events occur to trigger them. This means that messages related to several resources may be interleaved (if OpenTofu is running with concurrency above 1). The [`resource` object value](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) can be used to link multiple messages about a single resource. Message Types[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#message-types "Direct link to Message Types") ------------------------------------------------------------------------------------------------------------------------------ The following message types are supported: ### Generic Messages[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#generic-messages "Direct link to Generic Messages") * `version`: information about the OpenTofu version and the version of the schema used for the following messages * `log`: unstructured human-readable log lines * `diagnostic`: diagnostic warning or error messages; [see the `tofu validate` docs for more details on the format](https://opentofu.org/docs/v1.10/cli/commands/validate/#json) ### Operation Results[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#operation-results "Direct link to Operation Results") * `resource_drift`: describes a detected change to a single resource made outside of OpenTofu * `planned_change`: describes a planned change to a single resource * `change_summary`: summary of all planned or applied changes * `outputs`: list of all root module outputs ### Resource Progress[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-progress "Direct link to Resource Progress") * `apply_start`, `apply_progress`, `apply_complete`, `apply_errored`: sequence of messages indicating progress of a single resource through apply * `provision_start`, `provision_progress`, `provision_complete`, `provision_errored`: sequence of messages indicating progress of a single provisioner step * `refresh_start`, `refresh_complete`: sequence of messages indicating progress of a single resource through refresh Version Message[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#version-message "Direct link to Version Message") ------------------------------------------------------------------------------------------------------------------------------------ A machine-readable UI command output will always begin with a `version` message. The following message-specific keys are defined: * `tofu`: the OpenTofu version which emitted this message * `ui`: the machine-readable UI schema version defining the meaning of the following messages ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example "Direct link to Example") Code Block { "@level": "info", "@message": "OpenTofu 0.15.4", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.275359-04:00", "tofu": "0.15.4", "type": "version", "ui": "0.1.0"} Resource Drift[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-drift "Direct link to Resource Drift") --------------------------------------------------------------------------------------------------------------------------------- If drift is detected during planning, OpenTofu will emit a `resource_drift` message for each resource which has changed outside of OpenTofu. This message has an embedded `change` object with the following keys: * `resource`: object describing the address of the resource to be changed; see [resource object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) below for details * `action`: the action planned to be taken for the resource. Values: `update`, `delete`. This message does not include details about the exact changes which caused the change to be planned. That information is available in [the JSON plan output](https://opentofu.org/docs/v1.10/internals/json-format/) . ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-1 "Direct link to Example") Code Block { "@level": "info", "@message": "random_pet.animal: Drift detected (update)", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.705503-04:00", "change": { "resource": { "addr": "random_pet.animal", "module": "", "resource": "random_pet.animal", "implied_provider": "random", "resource_type": "random_pet", "resource_name": "animal", "resource_key": null }, "action": "update" }, "type": "resource_drift"} Planned Change[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#planned-change "Direct link to Planned Change") --------------------------------------------------------------------------------------------------------------------------------- At the end of a plan or before an apply, OpenTofu will emit a `planned_change` message for each resource which has changes to apply. This message has an embedded `change` object with the following keys: * `resource`: object describing the address of the resource to be changed; see [resource object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) below for details * `previous_resource`: object describing the previous address of the resource, if this change includes a configuration-driven move * `action`: the action planned to be taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete`, `move`. * `reason`: an optional reason for the change, only used when the action is `replace` or `delete`. Values: * `tainted`: resource was marked as tainted * `requested`: user requested that the resource be replaced, for example via the `-replace` plan flag * `cannot_update`: changes to configuration force the resource to be deleted and created rather than updated * `delete_because_no_resource_config`: no matching resource in configuration * `delete_because_wrong_repetition`: resource instance key has no corresponding `count` or `for_each` in configuration * `delete_because_count_index`: resource instance key is outside the range of the `count` argument * `delete_because_each_key`: resource instance key is not included in the `for_each` argument * `delete_because_no_module`: enclosing module instance is not in configuration This message does not include details about the exact changes which caused the change to be planned. That information is available in [the JSON plan output](https://opentofu.org/docs/v1.10/internals/json-format/) . ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-2 "Direct link to Example") Code Block { "@level": "info", "@message": "random_pet.animal: Plan to create", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.705503-04:00", "change": { "resource": { "addr": "random_pet.animal", "module": "", "resource": "random_pet.animal", "implied_provider": "random", "resource_type": "random_pet", "resource_name": "animal", "resource_key": null }, "action": "create" }, "type": "planned_change"} Change Summary[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#change-summary "Direct link to Change Summary") --------------------------------------------------------------------------------------------------------------------------------- OpenTofu outputs a change summary when a plan or apply operation completes. Both message types include a `changes` object, which has the following keys: * `add`: count of resources to be created (including as part of replacement) * `change`: count of resources to be changed in-place * `remove`: count of resources to be destroyed (including as part of replacement) * `operation`: one of `plan`, `apply`, or `destroy` ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-3 "Direct link to Example") Code Block { "@level": "info", "@message": "Apply complete! Resources: 1 added, 0 changed, 0 destroyed.", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.869168-04:00", "changes": { "add": 1, "change": 0, "remove": 0, "operation": "apply" }, "type": "change_summary"} Outputs[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#outputs "Direct link to Outputs") ------------------------------------------------------------------------------------------------------------ After a successful plan or apply, a message with type `outputs` contains the values of all root module output values. This message contains an `outputs` object, the keys of which are the output names. The outputs values are objects with the following keys: * `action`: for planned outputs, the action which will be taken for the output. Values: `noop`, `create`, `update`, `delete` * `value`: for applied outputs, the value of the output, encoded in JSON * `type`: for applied outputs, the detected HCL type of the output value * `sensitive`: boolean value, `true` if the output is sensitive and should be hidden from UI by default Note that `sensitive` outputs still include the `value` field, and integrating software should respect the sensitivity value as appropriate for the given use case. ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-4 "Direct link to Example") Code Block { "@level": "info", "@message": "Outputs: 1", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.869280-04:00", "outputs": { "pets": { "sensitive": false, "type": "string", "value": "smart-lizard" } }, "type": "outputs"} Operation Messages[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#operation-messages "Direct link to Operation Messages") --------------------------------------------------------------------------------------------------------------------------------------------- Performing OpenTofu operations to a resource will often result in several messages being emitted. The message types include: * `apply_start`: when starting to apply changes for a resource * `apply_progress`: periodically, showing elapsed time output * `apply_complete`: on successful operation completion * `apply_errored`: when an error is encountered during the operation * `provision_start`: when starting a provisioner step * `provision_progress`: on provisioner output * `provision_complete`: on successful provisioning * `provision_errored`: when an error is encountered during provisioning * `refresh_start`: when reading a resource during refresh * `refresh_complete`: on successful refresh Each of these messages has a `hook` object, which has different fields for each type. All hooks have a [`resource` object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) which identifies which resource is the subject of the operation. Apply Start[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#apply-start "Direct link to Apply Start") ------------------------------------------------------------------------------------------------------------------------ The `apply_start` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) identifying the resource * `action`: the action to be taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete` * `id_key` and `id_value`: a key/value pair used to identify this instance of the resource, omitted when unknown ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-5 "Direct link to Example") Code Block { "@level": "info", "@message": "random_pet.animal: Creating...", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.825308-04:00", "hook": { "resource": { "addr": "random_pet.animal", "module": "", "resource": "random_pet.animal", "implied_provider": "random", "resource_type": "random_pet", "resource_name": "animal", "resource_key": null }, "action": "create" }, "type": "apply_start"} Apply Progress[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#apply-progress "Direct link to Apply Progress") --------------------------------------------------------------------------------------------------------------------------------- The `apply_progress` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) identifying the resource * `action`: the action being taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete` * `elapsed_seconds`: time elapsed since the apply operation started, expressed as an integer number of seconds ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-6 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[4]: Still creating... [30s elapsed]", "@module": "tofu.ui", "@timestamp": "2021-03-17T09:34:26.222465-04:00", "hook": { "resource": { "addr": "null_resource.none[4]", "module": "", "resource": "null_resource.none[4]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 4 }, "action": "create", "elapsed_seconds": 30 }, "type": "apply_progress"} Apply Complete[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#apply-complete "Direct link to Apply Complete") --------------------------------------------------------------------------------------------------------------------------------- The `apply_complete` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) identifying the resource * `action`: the action taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete` * `id_key` and `id_value`: a key/value pair used to identify this instance of the resource, omitted when unknown * `elapsed_seconds`: time elapsed since the apply operation started, expressed as an integer number of seconds ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-7 "Direct link to Example") Code Block { "@level": "info", "@message": "random_pet.animal: Creation complete after 0s [id=smart-lizard]", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.826179-04:00", "hook": { "resource": { "addr": "random_pet.animal", "module": "", "resource": "random_pet.animal", "implied_provider": "random", "resource_type": "random_pet", "resource_name": "animal", "resource_key": null }, "action": "create", "id_key": "id", "id_value": "smart-lizard", "elapsed_seconds": 0 }, "type": "apply_complete"} Apply Errored[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#apply-errored "Direct link to Apply Errored") ------------------------------------------------------------------------------------------------------------------------------ The `apply_complete` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) identifying the resource * `action`: the action taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete` * `elapsed_seconds`: time elapsed since the apply operation started, expressed as an integer number of seconds The exact detail of the error will be rendered as a separate `diagnostic` message. ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-8 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: Creation errored after 10s", "@module": "tofu.ui", "@timestamp": "2021-03-26T16:38:54.013910-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "action": "create", "elapsed_seconds": 10 }, "type": "apply_errored"} Provision Start[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#provision-start "Direct link to Provision Start") ------------------------------------------------------------------------------------------------------------------------------------ The `provision_start` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) identifying the resource * `provisioner`: the type of provisioner ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-9 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: Provisioning with 'local-exec'...", "@module": "tofu.ui", "@timestamp": "2021-03-26T16:38:43.997431-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "provisioner": "local-exec" }, "type": "provision_start"} Provision Progress[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#provision-progress "Direct link to Provision Progress") --------------------------------------------------------------------------------------------------------------------------------------------- The `provision_progress` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) identifying the resource * `provisioner`: the type of provisioner * `output`: the output log from the provisioner One `provision_progress` message is output for each log line received from the provisioner. ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-10 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: (local-exec): Executing: [\"/bin/sh\" \"-c\" \"sleep 10 && exit 1\"]", "@module": "tofu.ui", "@timestamp": "2021-03-26T16:38:43.997869-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "provisioner": "local-exec", "output": "Executing: [\"/bin/sh\" \"-c\" \"sleep 10 && exit 1\"]" }, "type": "provision_progress"} Provision Complete[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#provision-complete "Direct link to Provision Complete") --------------------------------------------------------------------------------------------------------------------------------------------- The `provision_complete` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) identifying the resource * `provisioner`: the type of provisioner ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-11 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: (local-exec) Provisioning complete", "@module": "tofu.ui", "@timestamp": "2021-03-17T09:34:06.239043-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "provisioner": "local-exec" }, "type": "provision_complete"} Provision Errored[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#provision-errored "Direct link to Provision Errored") ------------------------------------------------------------------------------------------------------------------------------------------ The `provision_errored` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) identifying the resource * `provisioner`: the type of provisioner ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-12 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: (local-exec) Provisioning errored", "@module": "tofu.ui", "@timestamp": "2021-03-26T16:38:54.013572-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "provisioner": "local-exec" }, "type": "provision_errored"} Refresh Start[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#refresh-start "Direct link to Refresh Start") ------------------------------------------------------------------------------------------------------------------------------ The `refresh_start` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) identifying the resource * `id_key` and `id_value`: a key/value pair used to identify this instance of the resource ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-13 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: Refreshing state... [id=1971614370559474622]", "@module": "tofu.ui", "@timestamp": "2021-03-26T14:18:06.508915-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "id_key": "id", "id_value": "1971614370559474622" }, "type": "refresh_start"} Refresh Complete[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#refresh-complete "Direct link to Refresh Complete") --------------------------------------------------------------------------------------------------------------------------------------- The `refresh_complete` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) identifying the resource * `id_key` and `id_value`: a key/value pair used to identify this instance of the resource ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-14 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: Refresh complete [id=1971614370559474622]", "@module": "tofu.ui", "@timestamp": "2021-03-26T14:18:06.509371-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "id_key": "id", "id_value": "1971614370559474622" }, "type": "refresh_complete"} Resource Object[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object "Direct link to Resource Object") ------------------------------------------------------------------------------------------------------------------------------------ The `resource` object is a decomposed structure representing a resource address in configuration, which is used to identify which resource a given message is associated with. The object has the following keys: * `addr`: the full unique address of the resource as a string * `module`: the address of the module containing the resource, in the form `module.foo.module.bar`, or an empty string for a root module resource * `resource`: the module-relative address, which is identical to `addr` for root module resources * `resource_type`: the type of resource being addressed * `resource_name`: the name label for the resource * `resource_key`: the address key (`count` or `for_each` value), or `null` if the neither are used * `implied_provider`: the provider type implied by the resource type; this may not reflect the resource's provider if provider aliases are used ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-15 "Direct link to Example") Code Block { "addr": "module.pets.random_pet.pet[\"friend\"]", "module": "module.pets", "resource": "random_pet.pet[\"friend\"]", "implied_provider": "random", "resource_type": "random_pet", "resource_name": "pet", "resource_key": "friend"} Test Messages[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#test-messages "Direct link to Test Messages") ------------------------------------------------------------------------------------------------------------------------------ Running OpenTofu tests will result in several messages being emitted. The message types include: * `test_abstract`: Summary of test files and tests found * `test_file`: Summary of test file execution * `test_run`: Summary of test execution * `test_summary`: Summary of overall test file execution status and statistics Test Abstract[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#test-abstract "Direct link to Test Abstract") ------------------------------------------------------------------------------------------------------------------------------ The `test_abstract` message `test_abstract` object contains dynamic keys composed of the test file name: * `main.tftest.hcl`: list of tests found within the test file ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-16 "Direct link to Example") Code Block { "@level": "info", "@message": "Found 1 file and 1 run block", "@module": "tofu.ui", "@timestamp": "2024-04-20T17:24:48.418126+10:00", "test_abstract": { "main.tftest.hcl": [ "test" ] }, "type": "test_abstract"} Test File[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#test-file "Direct link to Test File") ------------------------------------------------------------------------------------------------------------------ The `test_file` message `test_file` object has the following keys: * `path`: the relative path of the test file * `status`: the overall test execution status ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-17 "Direct link to Example") Code Block { "@level": "info", "@message": "main.tftest.hcl... pass", "@module": "tofu.ui", "@testfile": "main.tftest.hcl", "@timestamp": "2024-04-20T17:24:48.588473+10:00", "test_file": { "path": "main.tftest.hcl", "status": "pass" }, "type": "test_file"} Test Run[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#test-run "Direct link to Test Run") --------------------------------------------------------------------------------------------------------------- The `test_run` message `test_run` object has the following keys: * `path`: the relative path of the test file * `run`: name of test that was executed * `status`: the overall test execution status ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-18 "Direct link to Example") Code Block { "@level": "info", "@message": " \"test\"... pass", "@module": "tofu.ui", "@testfile": "main.tftest.hcl", "@testrun": "test", "@timestamp": "2024-04-20T17:24:48.588519+10:00", "test_run": { "path": "main.tftest.hcl", "run": "test", "status": "pass" }, "type": "test_run"} Test Summary[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#test-summary "Direct link to Test Summary") --------------------------------------------------------------------------------------------------------------------------- The `test_summary` message `test_summary` object has the following keys: * `status`: the overall status of all tests executed * `passed`: the total number of tests that passed * `failed`: the total number of tests that failed * `errored`: the total number of tests that errored * `skipped`: the total number of tests that skipped ### Example[​](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-19 "Direct link to Example") Code Block { "@level": "info", "@message": "Success! 1 passed, 0 failed.", "@module": "tofu.ui", "@timestamp": "2024-04-20T17:24:48.716977+10:00", "test_summary": { "status": "pass", "passed": 1, "failed": 0, "errored": 0, "skipped": 0 }, "type": "test_summary"} * [Sample JSON Output](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#sample-json-output) * [Message Types](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#message-types) * [Generic Messages](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#generic-messages) * [Operation Results](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#operation-results) * [Resource Progress](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-progress) * [Version Message](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#version-message) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example) * [Resource Drift](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-drift) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-1) * [Planned Change](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#planned-change) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-2) * [Change Summary](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#change-summary) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-3) * [Outputs](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#outputs) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-4) * [Operation Messages](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#operation-messages) * [Apply Start](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#apply-start) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-5) * [Apply Progress](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#apply-progress) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-6) * [Apply Complete](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#apply-complete) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-7) * [Apply Errored](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#apply-errored) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-8) * [Provision Start](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#provision-start) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-9) * [Provision Progress](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#provision-progress) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-10) * [Provision Complete](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#provision-complete) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-11) * [Provision Errored](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#provision-errored) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-12) * [Refresh Start](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#refresh-start) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-13) * [Refresh Complete](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#refresh-complete) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-14) * [Resource Object](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#resource-object) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-15) * [Test Messages](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#test-messages) * [Test Abstract](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#test-abstract) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-16) * [Test File](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#test-file) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-17) * [Test Run](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#test-run) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-18) * [Test Summary](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#test-summary) * [Example](https://opentofu.org/docs/v1.10/internals/machine-readable-ui/#example-19) --- # OpenTofu vs. Custom Solutions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/vs/custom/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu vs. Custom Solutions ============================= Most organizations start by manually managing infrastructure through simple scripts or web-based interfaces. As the infrastructure grows, any manual approach to management becomes both error-prone and tedious, and many organizations begin to home-roll tooling to help automate the mechanical processes involved. These tools require time and resources to build and maintain. As tools of necessity, they represent the minimum viable features needed by an organization, being built to handle only the immediate needs. As a result, they are often hard to extend and difficult to maintain. Because the tooling must be updated in lockstep with any new features or infrastructure, it becomes the limiting factor for how quickly the infrastructure can evolve. OpenTofu is designed to tackle these challenges. It provides a simple, unified syntax, allowing almost any resource to be managed without learning new tooling. By capturing all the resources required, the dependencies between them can be resolved automatically so that operators do not need to remember and reason about them. Removing the burden of building the tool allows operators to focus on their infrastructure and not the tooling. Furthermore, OpenTofu is an open source tool. The community around OpenTofu helps to extend its features, fix bugs and document new use cases. OpenTofu helps solve a problem that exists in every organization and provides a standard that can be adopted to avoid reinventing the wheel between and within organizations. Its open source nature ensures it will be around in the long term. --- # Installing OpenTofu on RHEL, openSUSE, AlmaLinux and other RPM-based distributions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/intro/install/rpm/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Installing OpenTofu on RHEL, openSUSE, AlmaLinux and other RPM-based distributions ================================================================================== [Thank you to Buildkite for sponsoring the OpenTofu package hosting.](https://buildkite.com/) You can install OpenTofu from our RPM repository by following the step-by-step instructions below. Installing using the installer[​](https://opentofu.org/docs/v1.10/intro/install/rpm/#installing-using-the-installer "Direct link to Installing using the installer") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can use the OpenTofu installer script to run the installation. Code Block # Download the installer script:curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh -o install-opentofu.sh# Alternatively: wget --secure-protocol=TLSv1_2 --https-only https://get.opentofu.org/install-opentofu.sh -O install-opentofu.sh# Give it execution permissions:chmod +x install-opentofu.sh# Please inspect the downloaded script# Run the installer:./install-opentofu.sh --install-method rpm# Remove the installer:rm -f install-opentofu.sh Step-by-step instructions[​](https://opentofu.org/docs/v1.10/intro/install/rpm/#step-by-step-instructions "Direct link to Step-by-step instructions") ------------------------------------------------------------------------------------------------------------------------------------------------------ The following steps explain how to set up the OpenTofu RPM repositories. These instructions should work on most RPM-based Linux systems. ### Adding the OpenTofu repository[​](https://opentofu.org/docs/v1.10/intro/install/rpm/#adding-the-opentofu-repository "Direct link to Adding the OpenTofu repository") * Yum (RHEL/AlmaLinux/etc.) * Zypper (openSUSE) Create the `/etc/yum.repos.d/opentofu.repo` file by running the following command: Code Block cat >/etc/yum.repos.d/opentofu.repo </etc/zypp/repos.d/opentofu.repo < must be prepended by the , as in: Code Block tofu test -test-directory=extra-tests -filter=extra-tests/a.tftest.hcl * `-var 'foo=bar'` Set an input variable of the root module. Specify this option multiple times to add more than one variable. * `-var-file=filename` Set multiple variables from the specified file. In addition to this file, OpenTofu automatically loads `terraform.tfvars` and `*.auto.tfvars`. Use this option multiple times to specify more than one file. * `-json` Change the output format to JSON. * `-no-color` Disable colorized output in the command output. * `-verbose` Print the plan or state for each test run block as it executes. Note Use of variables in [module sources](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.10/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu test`. Directory structure[​](https://opentofu.org/docs/v1.10/cli/commands/test/#directory-structure "Direct link to Directory structure") ------------------------------------------------------------------------------------------------------------------------------------ The `tofu test` command supports two directory layouts, flat or nested: * Flat layout * Nested layout This layout places the `*.tftest.hcl` test files directly next to the `*.tf` files they test. There are no rules that each `*.tf` file must have its own test file, but it is a good practice to follow. Code Block .β”œβ”€β”€ main.tfβ”œβ”€β”€ main.tftest.hclβ”œβ”€β”€ foo.tfβ”œβ”€β”€ foo.tftest.hclβ”œβ”€β”€ bar.tf└── bar.tftest.hcl This layout places the `*.tftest.hcl` files in a separate `tests` directory. Similar to the flat layout, there are no rules that each `*.tf` file must have its own test file, but it is a good practice to follow. Code Block .β”œβ”€β”€ main.tfβ”œβ”€β”€ foo.tfβ”œβ”€β”€ bar.tf└── tests β”œβ”€β”€ main.tftest.hcl β”œβ”€β”€ foo.tftest.hcl └── bar.tftest.hcl ### Testing modules[​](https://opentofu.org/docs/v1.10/cli/commands/test/#testing-modules "Direct link to Testing modules") When testing modules, you can use one of the above directory structures for each module: * Flat layout * Nested layout With this layout, run `tofu test -test-directory=./path/to/module` to test the module in question. Code Block .β”œβ”€β”€ module1β”‚ β”œβ”€β”€ main.tfβ”‚ β”œβ”€β”€ main.tftest.hclβ”‚ β”œβ”€β”€ foo.tfβ”‚ β”œβ”€β”€ foo.tftest.hclβ”‚ β”œβ”€β”€ bar.tfβ”‚ └── bar.tftest.hcl└── module2 └── ... With this layout, **change your working directory to your module path** and run `tofu test` to test the module in question. Code Block .β”œβ”€β”€ module1β”‚ β”œβ”€β”€ main.tfβ”‚ β”œβ”€β”€ foo.tfβ”‚ β”œβ”€β”€ bar.tfβ”‚ └── testsβ”‚ β”œβ”€β”€ main.tftest.hclβ”‚ β”œβ”€β”€ foo.tftest.hclβ”‚ └── bar.tftest.hcl└── module2 └── ... Hint You can use the `-filter=sometest.tftest.hcl` option to run a limited set of test files. Use the option multiple times to run more than one test file. The `*.tftest.hcl` / `*.tofutest.hcl` file structure[​](https://opentofu.org/docs/v1.10/cli/commands/test/#the-tftesthcl--tofutesthcl-file-structure "Direct link to the-tftesthcl--tofutesthcl-file-structure") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The testing language of OpenTofu is similar to the main OpenTofu language and uses the same block structure. A test file consists of: * The **[`run` blocks](https://opentofu.org/docs/v1.10/cli/commands/test/#the-run-block) **: define your tests. * A **[`variables` block](https://opentofu.org/docs/v1.10/cli/commands/test/#the-variables-and-runvariables-blocks) ** (optional): define variables for all tests in the current file. * The **[`provider` blocks](https://opentofu.org/docs/v1.10/cli/commands/test/#the-providers-block) ** (optional): define the providers to be used for the tests. * The **[`mock_provider` blocks](https://opentofu.org/docs/v1.10/cli/commands/test/#the-mock_provider-blocks) ** (optional): define the providers to be mocked. * The **[`override_resource` blocks](https://opentofu.org/docs/v1.10/cli/commands/test/#the-override_resource-and-override_data-blocks) ** (optional): define the resources to be overridden. * The **[`override_data` blocks](https://opentofu.org/docs/v1.10/cli/commands/test/#the-override_resource-and-override_data-blocks) ** (optional): define the data sources to be overridden. * The **[`override_module` blocks](https://opentofu.org/docs/v1.10/cli/commands/test/#the-override_module-block) ** (optional): define the module calls to be overridden. ### The `run` block[​](https://opentofu.org/docs/v1.10/cli/commands/test/#the-run-block "Direct link to the-run-block") A `run` block contains a single test case which runs either `tofu apply` or `tofu plan` and then evaluates all `assert` blocks. Once the test is complete, it uses `tofu destroy` to remove the temporarily created resources. A `run` block consists of the following elements: | Name | Type | Description | | --- | --- | --- | | [`assert`](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runassert-block) | block | Defines assertions that check if your code (e.g. `main.tf`) created the infrastructure correctly. If you do not specify any `assert` blocks, OpenTofu simply applies the configuration without any assertions. | | [`module`](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runmodule-block) | block | Overrides the module being tested. You can use this to load a helper module for more elaborate tests. | | [`expect_failures`](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runexpect_failures-list) | list | A list of resources that should fail to provision in the current run. | | [`variables`](https://opentofu.org/docs/v1.10/cli/commands/test/#the-variables-and-runvariables-blocks) | block | Defines variables for the current test case. See the [variables section](https://opentofu.org/docs/v1.10/cli/commands/test/#variables)
. | | [`command`](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runcommand-setting-and-the-runplan_options-block) | `plan` or `apply` | Defines the command which OpenTofu will execute, `plan` or `apply`. Defaults to `apply`. | | [`plan_options`](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runcommand-setting-and-the-runplan_options-block) | block | Options for the `plan` or `apply` operation. | | [`providers`](https://opentofu.org/docs/v1.10/cli/commands/test/#the-providers-block) | object | Aliases for providers. | | [`override_resource`](https://opentofu.org/docs/v1.10/cli/commands/test/#the-override_resource-and-override_data-blocks) | block | Defines a resource to be overridden for the run. | | [`override_data`](https://opentofu.org/docs/v1.10/cli/commands/test/#the-override_resource-and-override_data-blocks) | block | Defines a data source to be overridden for the run. | | [`override_module`](https://opentofu.org/docs/v1.10/cli/commands/test/#the-override_module-block) | block | Defines a module call to be overridden for the run. | ### The `run.assert` block[​](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runassert-block "Direct link to the-runassert-block") You can specify `assert` blocks inside your `run` block to test the state of your infrastructure after the `apply` or `plan` operation is complete. There is no theoretical limit to the number of blocks you can define. Each block requires the following two attributes: 1. The `condition` is an [OpenTofu condition](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#condition-expressions) which should return `true` for the test to pass, `false` for the test to fail. The condition **must** reference a resource, data source, variable, output or module from the main code, otherwise OpenTofu will refuse to run the test. 2. The `error_message` is a string explaining what happened when the test fails. Example As a simple example, you can write an `assert` block as follows: * main.tftest.hcl * main.tf Code Block run "test" { assert { condition = file(local_file.test.filename) == "Hello world!" error_message = "Incorrect content in ${local_file.test.filename}." }} Code Block resource "local_file" "test" { filename = "${path.module}/test.txt" content = "Hello world!"} Please note that conditions only let you perform basic checks on the current OpenTofu state and use OpenTofu functions. **You cannot define additional data sources directly in your test code.** To work around this limitation, you can use [the `module` block](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runmodule-block) in order to load a helper module. ### The `run.module` block[​](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runmodule-block "Direct link to the-runmodule-block") In some cases you may find that the tools provided in the [condition expression](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#condition-expressions) are not enough to test if your code created the infrastructure correctly. You can use the `module` block to override the main module `tofu test` loads. This gives you the opportunity to create additional resources or data sources that you can use in your `assert` conditions. Its syntax is similar to loading modules in normal OpenTofu code: Code Block run "test" { module { source = "./some-module" }} The `module` block has the following two attributes: * The `source` attribute points to the directory of the module to load or any other [module source](https://opentofu.org/docs/v1.10/language/modules/sources/) . * The `version` specifies the version of the module you want to use. Note You cannot pass parameters directly in the `module` block as you may be used to from the normal OpenTofu code. Instead, you should use the [`variables` block](https://opentofu.org/docs/v1.10/cli/commands/test/#the-variables-and-runvariables-blocks) to pass parameters to your module. Example In this example project the `main.tf` file creates a Docker container with an `nginx` image exposed on port 8080. The `main.tftest.hcl` file needs to test if the webserver actually starts properly, but it cannot do that without a helper module. To create the `http` data source, the `main.tftest.hcl` file loads the `test-harness` module. The test helper then loads the main module and adds the data source to check the HTTP response. Note that the data source in the `test-harness` has an explicit dependency on `module.main` to make sure that the data source only returns once the main module has finished its work. * main.tf * main.tftest.hcl * test-harness/helper.tf Code Block terraform { required_providers { docker = { source = "kreuzwerker/docker" version = "3.0.2" } }}resource "docker_container" "webserver" { name = "nginx-test" image = "nginx" ports { internal = 80 external = 8080 }} Code Block run "http" { # Load the test helper instead of the main module: module { source = "./test-harness" } # Check if the webserver returned an HTTP 200 status code: assert { condition = data.http.test.status_code == 200 error_message = "Incorrect status code returned: ${data.http.test.status_code}" }} Code Block # Load the main module:module "main" { source = "../"}# Fetch the website so the assert can do its job:data "http" "test" { url = "http://localhost:8080" # Important! Wait for the main module to finish: depends_on = [module.main]} This project uses a [third-party provider](https://github.com/kreuzwerker/terraform-provider-docker) to launch the container. You can run it locally if you have a Docker Engine installed. ### The `variables` and `run.variables` blocks[​](https://opentofu.org/docs/v1.10/cli/commands/test/#the-variables-and-runvariables-blocks "Direct link to the-variables-and-runvariables-blocks") The code under test (e.g. `main.tf`) will often have variable blocks that you need to fill from your test case. You can provide variables to your test run using any of the following methods: | Order | Source | | --- | --- | | 1 | Environment variables with the `TF_VAR_` prefix. | | 2 | tfvar files specified in the current directory: `terraform.tfvars` and `*.auto.tfvars`. | | 3 | tfvar files specified in the tests directory: `tests/terraform.tfvars` and `tests/*.auto.tfvars`. | | 4 | Commandline variables defined using the flag `-var`, and the variables defined in the files specified by the flag `-var-file`. | | 5 | The variables from the `variables` block in a test file. | | 6 | The variables from the `variables` block in `run` block. | OpenTofu evaluates the variables in the order listed above, so you can use it to override the previously set variable. For example: * main.tftest.hcl * main.tf Code Block # First, set the variable here:variables { name = "OpenTofu"}run "basic" { assert { condition = output.greeting == "Hello OpenTofu!" error_message = "Incorrect greeting: ${output.greeting}" }}run "override" { # Override it for this test case only here: variables { name = "OpenTofu user" } assert { condition = output.greeting == "Hello OpenTofu user!" error_message = "Incorrect greeting: ${output.greeting}" }} Code Block variable "name" {}output "greeting" { value = "Hello ${var.name}!"} #### The `run` block outputs for variables[​](https://opentofu.org/docs/v1.10/cli/commands/test/#the-run-block-outputs-for-variables "Direct link to the-run-block-outputs-for-variables") It is also possible to use the earlier-executed `run` block module outputs to set another `run` block `variables` values. This can be useful when you need to pass values between different test cases. * main.tftest.hcl * mod/main.tf Code Block run "setup" { module { source = "./setup" }}run "test" { variables { filename_from_setup = run.setup.filename } # more assertions to run} Code Block output "filename" { value = "some_file.txt"} ### The `run.expect_failures` list[​](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runexpect_failures-list "Direct link to the-runexpect_failures-list") In some cases you may want to test deliberate failures of your code, for example to ensure your validation is working. You can use the `expect_failures` inside a `run` block to specify which variables or resources should fail when the code is run with the given parameters. For example, the test case below checks if the `instances` variable correctly fails validation when supplied with a negative number: * main.tftest.hcl * main.tf Code Block run "main" { command = plan variables { instances = -1 } expect_failures = [ var.instances, ]} Code Block variable "instances" { type = number validation { condition = var.instances >= 0 error_message = "The number of instances must be positive or zero" }} You can also use the `expect_failure` clause to check [lifecycle](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/) events like pre- or postconditions as well as the results of checks. Limitation The `expect_failure` list currently does not support testing resource creation failures. You must provide a [lifecycle](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/) event in order to use `expect_failure`. The example below checks if the misconfigured healthcheck fails. This ensures that the health check does not always return, even when it is running against the wrong endpoint. * main.tftest.hcl * main.tf Code Block run "test-failure" { variables { # This healthcheck endpoint won't exist: health_endpoint = "/nonexistent" } expect_failures = [ # We expect this to fail: check.health ]} Code Block variable "health_endpoint" { default = "/"}terraform { required_providers { docker = { source = "kreuzwerker/docker" version = "3.0.2" } }}resource "docker_container" "webserver" { name = "" image = "nginx" rm = true ports { internal = 80 external = 8080 }}check "health" { data "http" "www" { url = "http://localhost:8080${var.health_endpoint}" depends_on = [docker_container.webserver] } assert { condition = data.http.www.status_code == 200 error_message = "Invalid status code returned: ${data.http.www.status_code}" }} ### The `run.command` setting and the `run.plan_options` block[​](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runcommand-setting-and-the-runplan_options-block "Direct link to the-runcommand-setting-and-the-runplan_options-block") By default, `tofu test` uses `tofu apply` to create real infrastructure. In some cases, for example if the real infrastructure is very expensive or impossible to run for testing purposes, it can be useful to only run `tofu plan` instead. You can use the `command = plan` setting to perform a plan instead of an apply. The following example tests if the variable is correctly passed to the `docker_image` resource without actually applying the plan: * main.tftest.hcl * main.tf Code Block run "test" { command = plan plan_options { refresh = false } variables { image_name = "myapp" } assert { condition = docker_image.build.name == "myapp" error_message = "Missing build resource" }} Code Block variable "image_name" { default = "app"}terraform { required_providers { docker = { source = "kreuzwerker/docker" version = "3.0.2" } }}resource "docker_image" "build" { name = var.image_name build { context = "." }} Regardless of the `command` setting, you can use the `plan_options` block to specify the following additional options for both modes: | Name | Description | | --- | --- | | mode | Change this option from `normal` (default) to `refresh-only` in order to only refresh the local state from the remote infrastructure. | | refresh | Set this option to `false` to disable checking for external changes in relation to the state file. Similar to `tofu plan -refresh=false`. | | replace | Force replacing the specified list of resources, such as `[docker_image.build]` in the above example. Similar to `tofu plan -replace=docker_image.build`. | | target | Limit planning to the specified list of modules or resources. Similar to `tofu plan -target=docker_image.build`. | Tip You can use these options in conjunction with [provider overrides](https://opentofu.org/docs/v1.10/cli/commands/test/#the-providers-block) to create fully offline tests. See the [Providers section below](https://opentofu.org/docs/v1.10/cli/commands/test/#the-providers-block) for an example. ### The `providers` block[​](https://opentofu.org/docs/v1.10/cli/commands/test/#the-providers-block "Direct link to the-providers-block") In some cases you may want to override provider settings for test runs. You can use the `provider` blocks outside of `run` block to provide additional configuration options for providers, such as credentials for a test account. Code Block provider "aws" { // Add additional settings here} This feature can also enable partially or fully offline tests if the provider supports it. The following example illustrates a fully offline test with the AWS provider and an S3 bucket resource: * main.tftest.hcl * main.tf Code Block // Configure the AWS provider to run fake credentials and without// any validations. Not all providers support this, but when they// do, you can run fully offline tests.provider "aws" { access_key = "foo" secret_key = "bar" skip_credentials_validation = true skip_region_validation = true skip_metadata_api_check = true skip_requesting_account_id = true}run "test" { // Run in plan mode to skip applying: command = plan // Disable the refresh to prevent reaching out to the AWS API: plan_options { refresh = false } // Test if the bucket name is correctly passed to the aws_s3_bucket // resource: variables { bucket_name = "test" } assert { condition = aws_s3_bucket.test.bucket == "test" error_message = "Incorrect bucket name: ${aws_s3_bucket.test.bucket}" }} Code Block variable "bucket_name" {}provider "aws" { region = "us-east-2"}resource "aws_s3_bucket" "test" { bucket = var.bucket_name} #### Provider aliases[​](https://opentofu.org/docs/v1.10/cli/commands/test/#provider-aliases "Direct link to Provider aliases") In addition to provider overrides, you can alias providers in order to replace them with a different provider inside your `run` block. This is useful when you want to have two provider configurations within the same test file and switch between them. In the example below, the `sockettest` test case loads a different Docker provider configuration than the rest of the file. * main.tftest.hcl * main.tf Code Block # This is the default "docker" provider for this file:provider "docker" { host = "tcp://0.0.0.0:2376"}# This will be the override:provider "docker" { alias = "unixsocket" host = "unix:///var/run/docker.sock"}run "sockettest" { # Replace the "docker" provider for this test case only: providers = { docker = docker.unixsocket } assert { condition = docker_image.build.name == "myapp" error_message = "Missing build resource" }}// Add other tests with the original provider here. Code Block terraform { required_providers { docker = { source = "kreuzwerker/docker" version = "3.0.2" } }}resource "docker_image" "build" { name = "myapp" build { context = "." }} #### References to `run` module outputs and variables in `provider` blocks[​](https://opentofu.org/docs/v1.10/cli/commands/test/#references-to-run-module-outputs-and-variables-in-provider-blocks "Direct link to references-to-run-module-outputs-and-variables-in-provider-blocks") You can reference `var` (variables) and the `run` block module outputs in `provider` blocks to set up test providers based on dynamic configuration. Code Block variables { region = "us-west-2"}provider "aws" { region = var.region access_key = run.setup.access_key secret_key = run.setup.secret_key}run "setup" { # `mod` module has outputs access_key and secret_key module { source = "./mod" }# Actual run block behavior, such as asserts, are skipped for simplicity} ### The `mock_provider` blocks[​](https://opentofu.org/docs/v1.10/cli/commands/test/#the-mock_provider-blocks "Direct link to the-mock_provider-blocks") A `mock_provider` block allows you to replace provider configuration by a mocked one. In such scenario, creation and retrieval of provider resources and data sources will be skipped. Instead, OpenTofu will automatically generate all computed attributes and blocks to be used in tests. Note Learn more on how OpenTofu produces [automatically generated values](https://opentofu.org/docs/v1.10/cli/commands/test/#automatically-generated-values) . Mock providers also support `alias` field as well as `mock_resource` and `mock_data` blocks. In some cases, you may want to use default values instead of automatically generated ones by passing them inside `defaults` field of `mock_resource` or `mock_data` blocks. Additionally, you can use `override_resource` and `override_data` blocks to override resources or data sources in the scope of a single provider. Read more about overriding in [the next section](https://opentofu.org/docs/v1.10/cli/commands/test/#the-override_resource-and-override_data-blocks) . In the example below, we test if the bucket name is correctly passed to the resource without actually creating it: * main.tftest.hcl * main.tf Code Block // All resources and data sources provided by `aws.mock` provider// will be mocked. Their values will be automatically generated.mock_provider "aws" { alias = "mock"}// The same goes for `local` provider. Also, every `local_file`// data source will have its `content` set to `test`.mock_provider "local" { mock_data "local_file" { defaults = { content = "test" } }}// Test if the bucket name is correctly passed to the aws_s3_bucket// resource from the local file.run "test" { // Use `aws.mock` provider for this test run only. providers = { aws = aws.mock } assert { condition = aws_s3_bucket.test.bucket == "test" error_message = "Incorrect bucket name: ${aws_s3_bucket.test.bucket}" }} Code Block data "local_file" "bucket_name" { filename = "bucket_name.txt"}provider "aws" { region = "us-east-2"}resource "aws_s3_bucket" "test" { bucket = data.local_file.bucket_name.content} ### The `override_resource` and `override_data` blocks[​](https://opentofu.org/docs/v1.10/cli/commands/test/#the-override_resource-and-override_data-blocks "Direct link to the-override_resource-and-override_data-blocks") In some cases you may want to test your infrastructure with certain resources or data sources being overridden. You can use the `override_resource` or `override_data` blocks to skip creation and retrieval of these resources or data sources using the real provider. Instead, OpenTofu will automatically generate all computed attributes and blocks to be used in tests. Note Learn more on how OpenTofu produces [automatically generated values](https://opentofu.org/docs/v1.10/cli/commands/test/#automatically-generated-values) . These blocks consist of the following elements: | Name | Type | Description | | --- | --- | --- | | target | reference | Required. Address of the target resource or data source to be overridden. | | values | object | Custom values for computed attributes and blocks to be used instead of automatically generated. | You can use `override_resource` or `override_data` blocks for the whole test file or inside a single `run` block. The latter takes precedence if both specified for the same `target`. In the example below, we test if the bucket name is correctly passed to the resource without actually creating it: * main.tftest.hcl * main.tf Code Block // This data source will not be called for any run// in this `.tftest.hcl` file. Instead, `values` object// will be used to populate `content` attribute. Other// attributes and blocks will be automatically generated.override_data { target = data.local_file.bucket_name values = { content = "test" }}// Test if the bucket name is correctly passed to the aws_s3_bucket// resource from the local file.run "test" { // S3 bucket will not be created in AWS for this run, // but it's available to use in both tests and configuration. override_resource { target = aws_s3_bucket.test } assert { condition = aws_s3_bucket.test.bucket == "test" error_message = "Incorrect bucket name: ${aws_s3_bucket.test.bucket}" }} Code Block data "local_file" "bucket_name" { filename = "bucket_name.txt"}provider "aws" { region = "us-east-2"}resource "aws_s3_bucket" "test" { bucket = data.local_file.bucket_name.content} Limitation You cannot use `override_resource` or `override_data` with a single instance of a resource or data source. Each instance of a resource or data source must be overridden. ### Automatically generated values[​](https://opentofu.org/docs/v1.10/cli/commands/test/#automatically-generated-values "Direct link to Automatically generated values") Mocking resources and data sources requires OpenTofu to automatically generate computed attributes without calling respective providers. When generating these values, OpenTofu cannot follow custom provider logic, so it uses simple rules based on value type: | Attribute type | Generated value | | --- | --- | | number | `0` | | bool | `false` | | string | A random alpha-numeric string. | | list | An empty list. | | map | An empty map. | | set | An empty set. | | object | An object with its fields populated by the same logic recursively. | | tuple | An empty tuple. | Note You can set custom values to use instead of automatically generated ones via respective mock or override fields. Keep in mind, it's only possible for computed attributes and configuration values cannot be changed. ### The `override_module` block[​](https://opentofu.org/docs/v1.10/cli/commands/test/#the-override_module-block "Direct link to the-override_module-block") In some cases you may want to test your infrastructure with certain module calls being overridden. You can use the `override_module` block to ignore all the configuration provided by called module. In this case, OpenTofu will use custom values specified in the `override_module` block as module outputs. The block consist of the following elements: | Name | Type | Description | | --- | --- | --- | | target | reference | Required. Address of the target module call to be overridden. | | outputs | object | Values to be used as module call outputs. If an output is not specified, OpenTofu will set it to `null` by default. | You can use `override_module` block for the whole test file or inside a single `run` block. The latter takes precedence if both specified for the same `target`. In the example below, we test if the bucket name is correctly passed from the module without actually calling it: * main.tftest.hcl * main.tf * bucket\_meta/main.tf Code Block // All the module configuration will be ignored for this// module call. Instead, the `outputs` object will be used// to populate module outputs.override_module { target = module.bucket_meta outputs = { name = "test" tags = { Environment = "Test Env" } }}// Test if the bucket name is correctly passed to the aws_s3_bucket// resource from the module call.run "test" { // S3 bucket will not be created in AWS for this run, // but it's available to use in both tests and configuration. override_resource { target = aws_s3_bucket.test } assert { condition = aws_s3_bucket.test.bucket == "test" error_message = "Incorrect bucket name: ${aws_s3_bucket.test.bucket}" } assert { condition = aws_s3_bucket.test.tags["Environment"] == "Test Env" error_message = "Incorrect `Environment` tag: ${aws_s3_bucket.test.tags["Environment"]}" }} Code Block module "bucket_meta" { source = "./bucket_meta"}provider "aws" { region = "us-east-2"}resource "aws_s3_bucket" "test" { bucket = module.bucket_meta.name tags = module.bucket_meta.tags} Code Block data "local_file" "bucket_name" { filename = "bucket_name.txt"}output "name" { value = data.local_file.bucket_name.content}output "tags" { value = { Environment = "Dev" }} Limitation You cannot use `override_module` with a single instance of a module call. Each instance of a module call must be overridden. * [Usage](https://opentofu.org/docs/v1.10/cli/commands/test/#usage) * [Extension Precedence](https://opentofu.org/docs/v1.10/cli/commands/test/#extension-precedence) * [Options](https://opentofu.org/docs/v1.10/cli/commands/test/#options) * [Directory structure](https://opentofu.org/docs/v1.10/cli/commands/test/#directory-structure) * [Testing modules](https://opentofu.org/docs/v1.10/cli/commands/test/#testing-modules) * [The `*.tftest.hcl` / `*.tofutest.hcl` file structure](https://opentofu.org/docs/v1.10/cli/commands/test/#the-tftesthcl--tofutesthcl-file-structure) * [The `run` block](https://opentofu.org/docs/v1.10/cli/commands/test/#the-run-block) * [The `run.assert` block](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runassert-block) * [The `run.module` block](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runmodule-block) * [The `variables` and `run.variables` blocks](https://opentofu.org/docs/v1.10/cli/commands/test/#the-variables-and-runvariables-blocks) * [The `run.expect_failures` list](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runexpect_failures-list) * [The `run.command` setting and the `run.plan_options` block](https://opentofu.org/docs/v1.10/cli/commands/test/#the-runcommand-setting-and-the-runplan_options-block) * [The `providers` block](https://opentofu.org/docs/v1.10/cli/commands/test/#the-providers-block) * [The `mock_provider` blocks](https://opentofu.org/docs/v1.10/cli/commands/test/#the-mock_provider-blocks) * [The `override_resource` and `override_data` blocks](https://opentofu.org/docs/v1.10/cli/commands/test/#the-override_resource-and-override_data-blocks) * [Automatically generated values](https://opentofu.org/docs/v1.10/cli/commands/test/#automatically-generated-values) * [The `override_module` block](https://opentofu.org/docs/v1.10/cli/commands/test/#the-override_module-block) --- # OpenTofu Language Documentation | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page OpenTofu Language Documentation =============================== This is the documentation for OpenTofu's configuration language. It is relevant to users of [OpenTofu CLI](https://opentofu.org/docs/v1.10/cli/) , and [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software). OpenTofu's language is its primary user interface. Configuration files you write in OpenTofu language tell OpenTofu what plugins to install, what infrastructure to create, and what data to fetch. OpenTofu language also lets you define dependencies between resources and create multiple similar resources from a single configuration block. About the OpenTofu Language[​](https://opentofu.org/docs/v1.10/language/#about-the-opentofu-language "Direct link to About the OpenTofu Language") --------------------------------------------------------------------------------------------------------------------------------------------------- The main purpose of the OpenTofu language is declaring [resources](https://opentofu.org/docs/v1.10/language/resources/) , which represent infrastructure objects. All other language features exist only to make the definition of resources more flexible and convenient. An _OpenTofu configuration_ is a complete document in the OpenTofu language that tells OpenTofu how to manage a given collection of infrastructure. A configuration can consist of multiple files and directories. The syntax of the OpenTofu language consists of only a few basic elements: Code Block resource "aws_vpc" "main" { cidr_block = var.base_cidr_block} "" "" { # Block body = # Argument} * _Blocks_ are containers for other content and usually represent the configuration of some kind of object, like a resource. Blocks have a _block type,_ can have zero or more _labels,_ and have a _body_ that contains any number of arguments and nested blocks. Most of OpenTofu's features are controlled by top-level blocks in a configuration file. * _Arguments_ assign a value to a name. They appear within blocks. * _Expressions_ represent a value, either literally or by referencing and combining other values. They appear as values for arguments, or within other expressions. The OpenTofu language is declarative, describing an intended goal rather than the steps to reach that goal. The ordering of blocks and the files they are organized into are generally not significant; OpenTofu only considers implicit and explicit relationships between resources when determining an order of operations. ### Example[​](https://opentofu.org/docs/v1.10/language/#example "Direct link to Example") The following example describes a simple network topology for Amazon Web Services, just to give a sense of the overall structure and syntax of the OpenTofu language. Similar configurations can be created for other virtual network services, using resource types defined by other providers, and a practical network configuration will often contain additional elements not shown here. Code Block terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 1.0.4" } }}variable "aws_region" {}variable "base_cidr_block" { description = "A /16 CIDR range definition, such as 10.1.0.0/16, that the VPC will use" default = "10.1.0.0/16"}variable "availability_zones" { description = "A list of availability zones in which to create subnets" type = list(string)}provider "aws" { region = var.aws_region}resource "aws_vpc" "main" { # Referencing the base_cidr_block variable allows the network address # to be changed without modifying the configuration. cidr_block = var.base_cidr_block}resource "aws_subnet" "az" { # Create one subnet for each given availability zone. count = length(var.availability_zones) # For each subnet, use one of the specified availability zones. availability_zone = var.availability_zones[count.index] # By referencing the aws_vpc.main object, OpenTofu knows that the subnet # must be created only after the VPC is created. vpc_id = aws_vpc.main.id # Built-in functions and operators can be used for simple transformations of # values, such as computing a subnet address. Here we create a /20 prefix for # each subnet, using consecutive addresses for each availability zone, # such as 10.1.16.0/20 . cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 4, count.index+1)} * [About the OpenTofu Language](https://opentofu.org/docs/v1.10/language/#about-the-opentofu-language) * [Example](https://opentofu.org/docs/v1.10/language/#example) --- # Checks | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/checks/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Checks ====== The `check` block can validate your infrastructure outside the usual resource lifecycle. Check blocks address a gap between post-apply and functional validation of infrastructure. Check blocks allow you to define [custom conditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/) that execute on every OpenTofu plan or apply operation without affecting the overall status of an operation. Check blocks execute as the last step of a plan or apply after OpenTofu has planned or provisioned your infrastructure. Syntax[​](https://opentofu.org/docs/v1.10/language/checks/#syntax "Direct link to Syntax") ------------------------------------------------------------------------------------------- You can declare a `check` block with a local name, zero-to-one scoped [data sources](https://opentofu.org/docs/v1.10/language/checks/#scoped-data-sources) , and one-to-many [assertions](https://opentofu.org/docs/v1.10/language/checks/#assertions) . The following example loads the website and validates that it returns the expected status code `200`. Code Block check "health_check" { data "http" "opentofu_org" { url = "https://www.opentofu.org" } assert { condition = data.http.opentofu_org.status_code == 200 error_message = "${data.http.opentofu_org.url} returned an unhealthy status code" }} ### Scoped data sources[​](https://opentofu.org/docs/v1.10/language/checks/#scoped-data-sources "Direct link to Scoped data sources") You can use any data source from any provider as a scoped data source within a `check` block. A `check` block can optionally contain a nested (a.k.a. scoped) data source. This `data` block behaves like an external [data source](https://opentofu.org/docs/v1.10/language/data-sources/) , except you can not reference it outside its enclosing `check` block. Additionally, if a scoped data source's provider raises any errors, they are masked as warnings and do not prevent OpenTofu from continuing operation execution. You can use a scoped data source to validate the status of a piece of infrastructure outside of the usual OpenTofu resource lifecycle. [In the above example](https://opentofu.org/docs/v1.10/language/checks/#syntax) , if the `opentofu_org` data source fails to load, you receive a warning instead of a blocking error, which would occur if you declared this data source outside of a `check` block. #### Meta-Arguments[​](https://opentofu.org/docs/v1.10/language/checks/#meta-arguments "Direct link to Meta-Arguments") Scoped data sources support the `depends_on` and `provider` [meta-arguments](https://opentofu.org/docs/v1.10/language/resources/syntax/#meta-arguments) . Scoped data sources do not support the `count` or`for_each` meta-arguments. ##### `depends_on`[​](https://opentofu.org/docs/v1.10/language/checks/#depends_on "Direct link to depends_on") The `depends_on` meta-argument can be particularly powerful when used within scoped data sources. The first time OpenTofu creates the _initial_ plan for our [previous example](https://opentofu.org/docs/v1.10/language/checks/#syntax) , the plan fails because OpenTofu has not applied its configuration yet. Meaning this test fails because OpenTofu must still create the resources to make this website exist. Therefore, the first time OpenTofu runs this check, it always throws a potentially distracting error message. You can fix this by adding [`depends_on`](https://opentofu.org/docs/v1.10/language/meta-arguments/depends_on/) to your scoped data source, ensuring it depends on an essential piece of your site's infrastructure, such as the load balancer. The check returns `known after apply` until that crucial piece of your website is ready. This strategy avoids producing unnecessary warnings during setup, and the check executes during subsequent plans and applies. One problem with this strategy is that if the resource your scoped data source `depends_on` changes, the check block returns `known after apply` until OpenTofu has updated that resource. Depending on your use case, this behavior could be acceptable or problematic. We recommend implementing the `depends_on` meta-argument if your scoped data source depends on the existence of another resource without referencing it directly. ### Assertions[​](https://opentofu.org/docs/v1.10/language/checks/#assertions "Direct link to Assertions") Check blocks validate your custom assertions using `assert` blocks. Each `check` block must have at least one, but potentially many, `assert` blocks. Each `assert` block has a [`condition` attribute](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#condition-expressions) and an [`error_message` attribute](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#error-messages) . Unlike other [custom conditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/) , assertions do not affect OpenTofu's execution of an operation. A failed assertion reports a warning without halting the ongoing operation. This contrasts with other custom conditions, such as a postcondition, where OpenTofu produces an error immediately, halting the operation and blocking the application or planning of future resources. Condition arguments within `assert` blocks can refer to scoped data sources within the enclosing `check` block and any variables, resources, data sources, or module outputs within the current module. [Learn more about assertions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#checks-with-assertions) . ### Meta-Arguments[​](https://opentofu.org/docs/v1.10/language/checks/#meta-arguments-1 "Direct link to Meta-Arguments") Check blocks do not currently support [meta-arguments](https://opentofu.org/docs/v1.10/language/resources/syntax/#meta-arguments) . We are still collecting feedback on this feature, so if your use case would benefit from check blocks supporting meta-arguments, please [let us know](https://github.com/opentofu/opentofu/issues/new/choose) . Continuous validation in TACOS (TF Automation and Collaboration Software)[​](https://opentofu.org/docs/v1.10/language/checks/#continuous-validation-in-tacos-tf-automation-and-collaboration-software "Direct link to Continuous validation in TACOS (TF Automation and Collaboration Software)") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software) can automatically validate whether checks in a workspace’s configuration continue to pass after OpenTofu provisions new infrastructure. Choosing Checks or other Custom Conditions[​](https://opentofu.org/docs/v1.10/language/checks/#choosing-checks-or-other-custom-conditions "Direct link to Choosing Checks or other Custom Conditions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Check blocks offer the most _flexible_ validation solution within OpenTofu. You can reference outputs, variables, resources, and data sources within check assertions. You can also use checks to model every alternate [Custom Condition](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/) . However, that does not mean you should replace all your custom conditions with check blocks. There are major behavioral differences between check block assertions and other custom conditions, the main one being that check blocks do _not_ affect OpenTofu's execution of an operation. You can use this non-blocking behavior to decide the best type of validation for your use case. ### Outputs and variables[​](https://opentofu.org/docs/v1.10/language/checks/#outputs-and-variables "Direct link to Outputs and variables") [Output postconditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#outputs) and [variable validations](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#input-variable-validation) both make assertions around inputs and outputs. This is one of the cases where you might want OpenTofu to block further execution. For example, it is not helpful for OpenTofu to warn that an input variable is invalid after it applies an entire configuration with that input variable. In this case, a check block would warn of the invalid input variable _without_ interrupting the operation. A validation block for the same input variable would alert you of the invalid variable and halt the plan or apply operation. ### Resource Preconditions and Postconditions[​](https://opentofu.org/docs/v1.10/language/checks/#resource-preconditions-and-postconditions "Direct link to Resource Preconditions and Postconditions") The difference between [preconditions and postconditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#preconditions-and-postconditions) and check blocks is more nuanced. Preconditions are unique amongst the custom conditions in that they execute _before_ a resource change is applied or planned. [Choosing Between Preconditions and Postconditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#choosing-between-preconditions-and-postconditions) offers guidance on choosing between a precondition and a postcondition, and the same topics also apply to choosing between a precondition and a check block. You can often use postconditions interchangeably with check blocks to validate resources and data sources. For example, you can [rewrite the above `check` block example](https://opentofu.org/docs/v1.10/language/checks/#syntax) to use a postcondition instead. The below code uses a `postcondition` block to validate that the website returns the expected status code of `200`. Code Block data "http" "opentofu_org" { url = "https://www.opentofu.org" lifecycle { postcondition { condition = self.status_code == 200 error_message = "${self.url} returned an unhealthy status code" } }} Both the `check` and `postcondition` block examples validate that the website returns a `200` status code during a plan or an apply operation. The difference between the two blocks is how each handles failure. If a `postcondition` block fails, it _blocks_ OpenTofu from executing the current operation. If a `check` block fails, it _does not_ block OpenTofu from executing an operation. If the above example's postcondition fails, it is impossible to recover from. OpenTofu blocks any future plan or apply operations if your postcondition is unsatisfied during the planning stage. This problem occurs because the postcondition does not directly depend on OpenTofu configuration, but instead on the complex interactions between multiple resources. We recommend using check blocks to validate the status of infrastructure as a whole. We only recommend using postconditions when you want a guarantee on a single resource based on that resource's configuration. * [Syntax](https://opentofu.org/docs/v1.10/language/checks/#syntax) * [Scoped data sources](https://opentofu.org/docs/v1.10/language/checks/#scoped-data-sources) * [Assertions](https://opentofu.org/docs/v1.10/language/checks/#assertions) * [Meta-Arguments](https://opentofu.org/docs/v1.10/language/checks/#meta-arguments-1) * [Continuous validation in TACOS (TF Automation and Collaboration Software)](https://opentofu.org/docs/v1.10/language/checks/#continuous-validation-in-tacos-tf-automation-and-collaboration-software) * [Choosing Checks or other Custom Conditions](https://opentofu.org/docs/v1.10/language/checks/#choosing-checks-or-other-custom-conditions) * [Outputs and variables](https://opentofu.org/docs/v1.10/language/checks/#outputs-and-variables) * [Resource Preconditions and Postconditions](https://opentofu.org/docs/v1.10/language/checks/#resource-preconditions-and-postconditions) --- # Attributes as Blocks | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/attr-as-blocks/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Attributes as Blocks ==================== Note This page is an appendix to the OpenTofu documentation. Most users do not need to know the full details of this behavior. Summary[​](https://opentofu.org/docs/v1.10/language/attr-as-blocks/#summary "Direct link to Summary") ------------------------------------------------------------------------------------------------------ Many resource types use repeatable nested blocks to manage collections of sub-objects related to the primary resource. Rarely, some resource types _also_ support an argument with the same name as a nested block type, and will purge any sub-objects of that type if that argument is set to an empty list (` = []`). Most users do not need to know any further details of this "nested block or empty list" behavior. However, read further if you need to: * Use OpenTofu's [JSON syntax](https://opentofu.org/docs/v1.10/language/syntax/json/) with this type of resource. * Create a reusable module that wraps this type of resource. Details[​](https://opentofu.org/docs/v1.10/language/attr-as-blocks/#details "Direct link to Details") ------------------------------------------------------------------------------------------------------ The language makes a distinction between [argument syntax and nested block syntax](https://opentofu.org/docs/v1.10/language/syntax/configuration/#arguments-and-blocks) within blocks: * Argument syntax sets a named argument for the containing object. If the attribute has a default value then an explicitly-specified value entirely overrides that default. * Nested block syntax represents a related child object of the container that has its own set of arguments. Where multiple such objects are possible, multiple blocks of the same type can be present. If the nested attributes themselves have default values, they are honored for each nested block separately, merging in with any explicitly-defined arguments. The distinction between these is particularly important for [JSON syntax](https://opentofu.org/docs/v1.10/language/syntax/json/) because the same primitive JSON constructs (lists and objects) will be interpreted differently depending on whether a particular name is an argument or a nested block type. Defining a Fixed Object Collection Value[​](https://opentofu.org/docs/v1.10/language/attr-as-blocks/#defining-a-fixed-object-collection-value "Direct link to Defining a Fixed Object Collection Value") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When working with resource type arguments that behave in this way, it is valid and we recommend the use of nested block syntax whenever defining a fixed collection of objects: Code Block example { foo = "bar"}example { foo = "baz"} The above implicitly specifies a two-element list of objects assigned to the `example` argument, treating it as if it were a nested block type. If you need to explicitly call for zero `example` objects, you must use the argument syntax with an empty list: Code Block example = [] These two forms cannot be mixed; there cannot be both explicitly zero `example` objects and explicit single `example` blocks declared at the same time. For true nested blocks where this special behavior does not apply, assigning `[]` using argument syntax is not valid. The normal way to specify zero objects of a type is to write no nested blocks at all. Arbitrary Expressions with Argument Syntax[​](https://opentofu.org/docs/v1.10/language/attr-as-blocks/#arbitrary-expressions-with-argument-syntax "Direct link to Arbitrary Expressions with Argument Syntax") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Although we recommend using block syntax for simple cases for readability, the names that work in this mode _are_ defined as arguments, and so it is possible to use argument syntax to assign arbitrary dynamic expressions to them, as long as the expression has the expected result type: Code Block example = [ for name in var.names: { foo = name }] Code Block # Not recommended, but valid: a constant list-of-objects expressionexample = [ { foo = "bar" }, { foo = "baz" },] Because of the rule that argument declarations like this fully override any default value, when creating a list-of-objects expression directly the usual handling of optional arguments does not apply, so all of the arguments must be assigned a value, even if it's an explicit `null`: Code Block example = [ { # Cannot omit foo in this case, even though it would be optional in the # nested block syntax. foo = null },] If you are writing a reusable module that allows callers to pass in a list of objects to assign to such an argument, you may wish to use the `merge` function to populate any attributes the user didn't explicitly set, in order to give the module user the effect of optional arguments: Code Block example = [ for ex in var.examples: merge({ foo = null # (or any other suitable default value) }, ex)] For the arguments that use the attributes-as-blocks usage mode, the above is a better pattern than using [`dynamic` blocks](https://opentofu.org/docs/v1.10/language/expressions/dynamic-blocks/) because the case where the caller provides an empty list will result in explicitly assigning an empty list value, rather than assigning no value at all and thus retaining and ignoring any existing objects. `dynamic` blocks are required for dynamically-generating _normal_ nested blocks, though. In JSON syntax[​](https://opentofu.org/docs/v1.10/language/attr-as-blocks/#in-json-syntax "Direct link to In JSON syntax") --------------------------------------------------------------------------------------------------------------------------- Arguments that use this special mode are specified in JSON syntax always using the [JSON expression mapping](https://opentofu.org/docs/v1.10/language/syntax/json/#expression-mapping) to produce a list of objects. The interpretation of these values in JSON syntax is, therefore, equivalent to that described under _Arbitrary Expressions with Argument Syntax_ above, but expressed in JSON syntax instead. Due to the ambiguity of the JSON syntax, there is no way to distinguish based on the input alone between argument and nested block usage, so the JSON syntax cannot support the nested block processing mode for these arguments. This is, unfortunately, one necessary concession on the equivalence between native syntax and JSON syntax made pragmatically for compatibility with existing provider design patterns. Providers may phase out such patterns in future major releases. * [Summary](https://opentofu.org/docs/v1.10/language/attr-as-blocks/#summary) * [Details](https://opentofu.org/docs/v1.10/language/attr-as-blocks/#details) * [Defining a Fixed Object Collection Value](https://opentofu.org/docs/v1.10/language/attr-as-blocks/#defining-a-fixed-object-collection-value) * [Arbitrary Expressions with Argument Syntax](https://opentofu.org/docs/v1.10/language/attr-as-blocks/#arbitrary-expressions-with-argument-syntax) * [In JSON syntax](https://opentofu.org/docs/v1.10/language/attr-as-blocks/#in-json-syntax) --- # JSON Output Format | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/internals/json-format/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page JSON Output Format ================== When OpenTofu plans to make changes, it prints a human-readable summary to the terminal. It can also, when run with `-out=`, write a much more detailed binary plan file, which can later be used to apply those changes. Since the format of plan files isn't suited for use with external tools (and likely never will be), OpenTofu can output a machine-readable JSON representation of a plan file's changes. It can also convert state files to the same format, to simplify data loading and provide better long-term compatibility. Use `tofu show -json ` to generate a JSON representation of a plan or state file. See [the `tofu show` documentation](https://opentofu.org/docs/v1.10/cli/commands/show/) for more details. The output includes a `format_version` key, which has value `"1.0"`. The semantics of this version are: * We will increment the minor version, e.g. `"1.1"`, for backward-compatible changes or additions. Ignore any object properties with unrecognized names to remain forward-compatible with future minor versions. * We will increment the major version, e.g. `"2.0"`, for changes that are not backward-compatible. Reject any input which reports an unsupported major version. We will introduce new major versions only within the bounds of [the OpenTofu 1.0 Compatibility Promises](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/) . Format Summary[​](https://opentofu.org/docs/v1.10/internals/json-format/#format-summary "Direct link to Format Summary") ------------------------------------------------------------------------------------------------------------------------- The following sections describe the JSON output format by example, using a pseudo-JSON notation. Important elements are described with comments, which are prefixed with `//`. To avoid excessive repetition, we've split the complete format into several discrete sub-objects, described under separate headers. References wrapped in angle brackets (like ``) are placeholders which, in the real output, would be replaced by an instance of the specified sub-object. The JSON output format consists of the following objects and sub-objects: * [State Representation](https://opentofu.org/docs/v1.10/internals/json-format/#state-representation) β€”Β The complete top-level object returned by `tofu show -json `. * [Plan Representation](https://opentofu.org/docs/v1.10/internals/json-format/#plan-representation) β€”Β The complete top-level object returned by `tofu show -json `. * [Values Representation](https://opentofu.org/docs/v1.10/internals/json-format/#values-representation) β€”Β A sub-object of both plan and state output that describes current state or planned state. * [Configuration Representation](https://opentofu.org/docs/v1.10/internals/json-format/#configuration-representation) β€”Β A sub-object of plan output that describes a parsed OpenTofu configuration. * [Expression Representation](https://opentofu.org/docs/v1.10/internals/json-format/#expression-representation) β€”Β A sub-object of a configuration representation that describes an unevaluated expression. * [Block Expressions Representation](https://opentofu.org/docs/v1.10/internals/json-format/#block-expressions-representation) β€”Β A sub-object of a configuration representation that describes the expressions nested inside a block. * [Change Representation](https://opentofu.org/docs/v1.10/internals/json-format/#change-representation) β€”Β A sub-object of plan output that describes changes to an object. * [Checks Representation](https://opentofu.org/docs/v1.10/internals/json-format/#checks-representation) β€” A property of both the plan and state representations that describes the current status of any checks (e.g. preconditions and postconditions) in the configuration. State Representation[​](https://opentofu.org/docs/v1.10/internals/json-format/#state-representation "Direct link to State Representation") ------------------------------------------------------------------------------------------------------------------------------------------- State does not have any significant metadata not included in the common [values representation](https://opentofu.org/docs/v1.10/internals/json-format/#values-representation) , so the `` uses the following format: Code Block { // "values" is a values representation object derived from the values in the // state. Because the state is always fully known, this is always complete. "values": // The key here is left unchanged in OpenTofu for compatibility reasons. "terraform_version": "version.string"} Plan Representation[​](https://opentofu.org/docs/v1.10/internals/json-format/#plan-representation "Direct link to Plan Representation") ---------------------------------------------------------------------------------------------------------------------------------------- A plan consists of a prior state, the configuration that is being applied to that state, and the set of changes OpenTofu plans to make to achieve that. For ease of consumption by callers, the plan representation includes a partial representation of the values in the final state (using a [value representation](https://opentofu.org/docs/v1.10/internals/json-format/#values-representation) ), allowing callers to easily analyze the planned outcome using similar code as for analyzing the prior state. Code Block { "format_version": "1.0", // "prior_state" is a representation of the state that the configuration is // being applied to, using the state representation described above. "prior_state": , // "configuration" is a representation of the configuration being applied to the // prior state, using the configuration representation described above. "configuration": , // "planned_values" is a description of what is known so far of the outcome in // the standard value representation, with any as-yet-unknown values omitted. "planned_values": , // "proposed_unknown" is a representation of the attributes, including any // potentially-unknown attributes. Each value is replaced with "true" or // "false" depending on whether it is known in the proposed plan. "proposed_unknown": , // "variables" is a representation of all the variables provided for the given // plan. This is structured as a map similar to the output map so we can add // additional fields in later. "variables": { "varname": { "value": "varvalue", "deprecated": "The variable is deprecated, use another one instead" }, }, // "resource_changes" is a description of the individual change actions that // OpenTofu plans to use to move from the prior state to a new state // matching the configuration. "resource_changes": [ // Each element of this array describes the action to take // for one instance object. All resources in the // configuration are included in this list. { // "address" is the full absolute address of the resource instance this // change applies to, in the same format as addresses in a value // representation. "address": "module.child.aws_instance.foo[0]", // "previous_address" is the full absolute address of this resource // instance as it was known after the previous OpenTofu run. // Included only if the address has changed, e.g. by handling // a "moved" block in the configuration. "previous_address": "module.instances.aws_instance.foo[0]", // "module_address", if set, is the module portion of the above address. // Omitted if the instance is in the root module. "module_address": "module.child", // "mode", "type", "name", and "index" have the same meaning as in a // value representation. "mode": "managed", "type": "aws_instance", "name": "foo", "index": 0, // "deposed", if set, indicates that this action applies to a "deposed" // object of the given instance rather than to its "current" object. // Omitted for changes to the current object. "address" and "deposed" // together form a unique key across all change objects in a particular // plan. The value is an opaque key representing the specific deposed // object. "deposed": "deadbeef", // "change" describes the change that will be made to the indicated // object. The is detailed in a section below. "change": , // "action_reason" is some optional extra context about why the // actions given inside "change" were selected. This is the JSON // equivalent of annotations shown in the normal plan output like // "is tainted, so it must be replaced" as opposed to just "must be // replaced". // // These reason codes are display hints only and the set of possible // hints may change over time. Users of this must be prepared to // encounter unrecognized reasons and treat them as unspecified reasons. // // The current set of possible values is: // - "replace_because_tainted": the object in question is marked as // "tainted" in the prior state, so OpenTofu planned to replace it. // - "replace_because_cannot_update": the provider indicated that one // of the requested changes isn't possible without replacing the // existing object with a new object. // - "replace_by_request": the user explicitly called for this object // to be replaced as an option when creating the plan, which therefore // overrode what would have been a "no-op" or "update" action otherwise. // - "delete_because_no_resource_config": OpenTofu found no resource // configuration corresponding to this instance. // - "delete_because_no_module": The resource instance belongs to a // module instance that's no longer declared, perhaps due to changing // the "count" or "for_each" argument on one of the containing modules. // - "delete_because_wrong_repetition": The instance key portion of the // resource address isn't of a suitable type for the corresponding // resource's configured repetition mode (count, for_each, or neither). // - "delete_because_count_index": The corresponding resource uses count, // but the instance key is out of range for the currently-configured // count value. // - "delete_because_each_key": The corresponding resource uses for_each, // but the instance key doesn't match any of the keys in the // currently-configured for_each value. // - "read_because_config_unknown": For a data resource, OpenTofu cannot // read the data during the plan phase because of values in the // configuration that won't be known until the apply phase. // - "read_because_dependency_pending": For a data resource, OpenTofu // cannot read the data during the plan phase because the data // resource depends on at least one managed resource that also has // a pending change in the same plan. // // If there is no special reason to note, OpenTofu will omit this // property altogether. action_reason: "replace_because_tainted" } ], // "resource_drift" is a description of the changes OpenTofu detected // when it compared the most recent state to the prior saved state. "resource_drift": [ { // "resource_drift" uses the same object structure as // "resource_changes". } ], // "relevant_attributes" lists the sources of all values contributing to // changes in the plan. You can use "relevant_attributes" to filter // "resource_drift" and determine which external changes may have affected the // plan result. "relevant_attributes": [ { "resource": "aws_instance.foo", "attribute": "attr", } ] // "output_changes" describes the planned changes to the output values of the // root module. "output_changes": { // Keys are the defined output value names. "foo": { // "change" describes the change that will be made to the indicated output // value, using the same representation as for resource changes except // that the only valid actions values are: // ["create"] // ["update"] // ["delete"] // OpenTofu is not yet fully able to // track changes to output values, so the actions indicated may not be // fully accurate, but the "after" value will always be correct. "change": , } }, // "checks" describes the partial results for any checkable objects, such as // resources with postconditions, with as much information as OpenTofu can // recognize at plan time. Some objects will have status "unknown" to // indicate that their status will only be determined after applying the plan. "checks" , // "errored" indicates whether planning failed. An errored plan cannot be applied, // but the actions planned before failure may help to understand the error. "errored": false} This overall plan structure, fully expanded, is what will be printed by the `tofu show -json ` command. Values Representation[​](https://opentofu.org/docs/v1.10/internals/json-format/#values-representation "Direct link to Values Representation") ---------------------------------------------------------------------------------------------------------------------------------------------- A values representation is used in both state and plan output to describe current state (which is always complete) and planned state (which omits values not known until apply). The following example illustrates the structure of a ``: Code Block { // "outputs" describes the outputs from the root module. Outputs from // descendent modules are not available because they are not retained in all // of the underlying structures we will build this values representation from. "outputs": { "private_ip": { "value": "192.168.3.2", "type": "string", "sensitive": false, "deprecated": "This output is deprecated, use another one instead" } }, // "root_module" describes the resources and child modules in the root module. "root_module": { "resources": [ { // "address" is the absolute resource address, which callers must consider // opaque but may do full string comparisons with other address strings or // pass this verbatim to other OpenTofu commands that are documented to // accept absolute resource addresses. The module-local portions of this // address are extracted in other properties below. "address": "aws_instance.example[1]", // "mode" can be "managed", for resources, or "data", for data resources "mode": "managed", "type": "aws_instance", "name": "example", // If the count or for_each meta-arguments are set for this resource, the // additional key "index" is present to give the instance index key. This // is omitted for the single instance of a resource that isn't using count // or for_each. "index": 1, // "provider_name" is the name of the provider that is responsible for // this resource. This is only the provider name, not a provider // configuration address, and so no module path nor alias will be // indicated here. This is included to allow the property "type" to be // interpreted unambiguously in the unusual situation where a provider // offers a resource type whose name does not start with its own name, // such as the "googlebeta" provider offering "google_compute_instance". "provider_name": "aws", // "schema_version" indicates which version of the resource type schema // the "values" property conforms to. "schema_version": 2, // "values" is the JSON representation of the attribute values of the // resource, whose structure depends on the resource type schema. Any // unknown values are omitted or set to null, making them // indistinguishable from absent values; callers which need to distinguish // unknown from unset must use the plan-specific or configuration-specific // structures described in later sections. "values": { "id": "i-abc123", "instance_type": "t2.micro", // etc, etc }, // "sensitive_values" is the JSON representation of the sensitivity of // the resource's attribute values. Only attributes which are sensitive // are included in this structure. "sensitive_values": { "id": true, } } ] "child_modules": [ // Each entry in "child_modules" has the same structure as the root_module // object, with the additional "address" property shown below. { // "address" is the absolute module address, which callers must treat as // opaque but may do full string comparisons with other module address // strings and may pass verbatim to other OpenTofu commands that are // documented as accepting absolute module addresses. "address": "module.child", // "resources" is the same as in "root_module" above "resources": [ { "address": "module.child.aws_instance.foo", // etc, etc } ], // Each module object can optionally have its own // nested "child_modules", recursively describing the // full module tree. "child_modules": [ ... ], } ] }} The translation of attribute and output values is the same intuitive mapping from HCL types to JSON types used by OpenTofu's [`jsonencode`](https://opentofu.org/docs/v1.10/language/functions/jsonencode/) function. This mapping does lose some information: lists, sets, and tuples all lower to JSON arrays while maps and objects both lower to JSON objects. Unknown values and null values are both treated as absent or null. Output values include a `"type"` field, which is a [serialization of the value's type](https://pkg.go.dev/github.com/zclconf/go-cty/cty#Type.MarshalJSON) . For primitive types this is a string value, such as `"number"` or `"bool"`. Complex types are represented as a nested JSON array, such as `["map","string"]` or `["object",{"a":"number"}]`. This can be used to reconstruct the output value with the correct type. Only the "current" object for each resource instance is described. "Deposed" objects are not reflected in this structure at all; in plan representations, you can refer to the change representations for further details. The intent of this structure is to give a caller access to a similar level of detail as is available to expressions within the configuration itself. This common representation is not suitable for all use-cases because it loses information compared to the data structures it is built from. For more complex needs, use the more elaborate changes and configuration representations. Configuration Representation[​](https://opentofu.org/docs/v1.10/internals/json-format/#configuration-representation "Direct link to Configuration Representation") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- Configuration is the most complicated structure in OpenTofu, since it includes unevaluated expression nodes and other complexities. Because the configuration models are produced at a stage prior to expression evaluation, it is not possible to produce a values representation for configuration. Instead, we describe the physical structure of the configuration, giving access to constant values where possible and allowing callers to analyze any references to other objects that are present: Code Block { // "provider_configs" describes all of the provider configurations throughout // the configuration tree, flattened into a single map for convenience since // provider configurations are the one concept in OpenTofu that can span // across module boundaries. "provider_config": { // Keys in the provider_configs map are to be considered opaque by callers, // and used just for lookups using the "provider_config_key" property in each // resource object. "opaque_provider_ref_aws": { // "name" is the name of the provider without any alias "name": "aws", // "full_name" is the fully-qualified provider name "full_name": "registry.opentofu.org/hashicorp/aws", // "alias" is the alias set for a non-default configuration, or unset for // a default configuration. "alias": "foo", // "module_address" is included only for provider configurations that are // declared in a descendent module, and gives the opaque address for the // module that contains the provider configuration. "module_address": "module.child", // "expressions" describes the provider-specific content of the // configuration block, as a block expressions representation (see section // below). "expressions": } }, // "root_module" describes the root module in the configuration, and serves // as the root of a tree of similar objects describing descendent modules. "root_module": { // "outputs" describes the output value configurations in the module. "outputs": { // Property names here are the output value names "example": { "expression": , "sensitive": false, "deprecated": "This output is deprecated, use another one instead" } }, // "resources" describes the "resource" and "data" blocks in the module // configuration. "resources": [ { // "address" is the opaque absolute address for the resource itself. "address": "aws_instance.example", // "mode", "type", and "name" have the same meaning as for the resource // portion of a value representation. "mode": "managed", "type": "aws_instance", "name": "example", // "provider_config_key" is the key into "provider_configs" (shown // above) for the provider configuration that this resource is // associated with. If the provider configuration was passed into // this module from the parent module, the key will point to the // original provider config block. "provider_config_key": "opaque_provider_ref_aws", // "provisioners" is an optional field which describes any provisioners. // Connection info will not be included here. "provisioners": [ { "type": "local-exec", // "expressions" describes the provisioner configuration "expressions": }, ], // "expressions" describes the resource-type-specific content of the // configuration block. "expressions": , // "schema_version" is the schema version number indicated by the // provider for the type-specific arguments described in "expressions". "schema_version": 2, // "count_expression" and "for_each_expression" describe the expressions // given for the corresponding meta-arguments in the resource // configuration block. These are omitted if the corresponding argument // isn't set. "count_expression": , "for_each_expression": }, ], // "module_calls" describes the "module" blocks in the module. During // evaluation, a module call with count or for_each may expand to multiple // module instances, but in configuration only the block itself is // represented. "module_calls": { // Key is the module call name chosen in the configuration. "child": { // "resolved_source" is the resolved source address of the module, after // any normalization and expansion. This could be either a // go-getter-style source address or a local path starting with "./" or // "../". If the user gave a registry source address then this is the // final location of the module as returned by the registry, after // following any redirect indirection. "resolved_source": "./child" // "expressions" describes the expressions for the arguments within the // block that correspond to input variables in the child module. "expressions": , // "count_expression" and "for_each_expression" describe the expressions // given for the corresponding meta-arguments in the module // configuration block. These are omitted if the corresponding argument // isn't set. "count_expression": , "for_each_expression": , // "module" is a representation of the configuration of the child module // itself, using the same structure as the "root_module" object, // recursively describing the full module tree. "module": } } }} ### Expression Representation[​](https://opentofu.org/docs/v1.10/internals/json-format/#expression-representation "Direct link to Expression Representation") Each unevaluated expression in the configuration is represented with an `` object with the following structure: Code Block { // "constant_value" is set only if the expression contains no references to // other objects, in which case it gives the resulting constant value. This is // mapped as for the individual values in a value representation. "constant_value": "hello", // Alternatively, "references" will be set to a list of references in the // expression. Multi-step references will be unwrapped and duplicated for each // significant traversal step, allowing callers to more easily recognize the // objects they care about without attempting to parse the expressions. // Callers should only use string equality checks here, since the syntax may // be extended in future releases. "references": [ "data.template_file.foo[1].vars[\"baz\"]", "data.template_file.foo[1].vars", // implied by previous "data.template_file.foo[1]", // implied by previous "data.template_file.foo", // implied by previous "module.foo.bar", "module.foo", // implied by the previous "var.example[0]", "var.example", // implied by the previous // Partial references like "data" and "module" are not included, because // OpenTofu considers "module.foo" to be an atomic reference, not an // attribute access. ]} Note Expressions in `dynamic` blocks are not included in the configuration representation. ### Block Expressions Representation[​](https://opentofu.org/docs/v1.10/internals/json-format/#block-expressions-representation "Direct link to Block Expressions Representation") In some cases, it is the entire content of a block (possibly after certain special arguments have already been handled and removed) that must be represented. For that, we have an `` structure: Code Block { // Attribute arguments are mapped directly with the attribute name as key and // an as value. "ami": , "instance_type": , // Nested block arguments are mapped as either a single nested // or an array object of these, depending on the // block nesting mode chosen in the schema. // - "single" nesting is a direct // - "list" and "set" produce arrays // - "map" produces an object "root_block_device": , "ebs_block_device": [ ]} For now we expect callers to just hard-code assumptions about the schemas of particular resource types in order to process these expression representations. In a later release we will add new inspection commands to return machine-readable descriptions of the schemas themselves, allowing for more generic handling in programs such as visualization tools. Change Representation[​](https://opentofu.org/docs/v1.10/internals/json-format/#change-representation "Direct link to Change Representation") ---------------------------------------------------------------------------------------------------------------------------------------------- A `` describes the change to the indicated object. Code Block { // "actions" are the actions that will be taken on the object selected by the // properties below. // Valid actions values are: // ["no-op"] // ["create"] // ["read"] // ["update"] // ["delete", "create"] // ["create", "delete"] // ["delete"] // ["forget"] // The two "replace" actions are represented in this way to allow callers to // e.g. just scan the list for "delete" to recognize all three situations // where the object will be deleted, allowing for any new deletion // combinations that might be added in future. "actions": ["update"], // Before and After are representations of the object value both before and // after the action. For ["delete"] and ["forget"] actions, the "after" // value is unset. For ["create"] the "before" is unset. For ["no-op"], the // before and after values are identical. The "after" value will be // incomplete if there are values within it that won't be known until after // apply. "before": , "after": , // "after_unknown" is an object value with similar structure to "after", but // with all unknown leaf values replaced with "true", and all known leaf // values omitted. This can be combined with "after" to reconstruct a full // value after the action, including values which will only be known after // apply. "after_unknown": { "id": true }, // "before_sensitive" and "after_sensitive" are object values with similar // structure to "before" and "after", but with all sensitive leaf values // replaced with true, and all non-sensitive leaf values omitted. These // objects should be combined with "before" and "after" to prevent accidental // display of sensitive values in user interfaces. "before_sensitive": {}, "after_sensitive": { "triggers": { "boop": true } }, // "replace_paths" is an array of arrays representing a set of paths into the // object value which resulted in the action being "replace". This will be // omitted if the action is not replace, or if no paths caused the // replacement (for example, if the resource was tainted). Each path // consists of one or more steps, each of which will be a number or a // string. "replace_paths": [["triggers"]]} Checks Representation[​](https://opentofu.org/docs/v1.10/internals/json-format/#checks-representation "Direct link to Checks Representation") ---------------------------------------------------------------------------------------------------------------------------------------------- Warning The JSON representation of checks is experimental and some details may change in future OpenTofu versions based on feedback, even in minor releases of OpenTofu CLI. A `` describes the current state of a checkable object in the configuration. For example, a resource with one or more preconditions or postconditions is an example of a checkable object, and its check state represents the results of those conditions. Code Block [ { // "address" describes the address of the checkable object whose status // this object is describing. "address": { // "kind" specifies what kind of checkable object this is. Different // kinds of object will have different additional properties inside the // address object, but all kinds include both "kind" and "to_display". // The two valid kinds are "resource" and "output_value". "kind": "resource", // "to_display" contains an opaque string representation of the address // of the object that is suitable for display in a UI. For consumers that // have special handling depending on the value of "kind", this property // is a good fallback to use when the application doesn't recognize the // "kind" value. "to_display": "aws_instance.example", // "mode" is included for kind "resource" only, and specifies the resource // mode which can either be "managed" (for "resource" blocks) or "data" // (for "data" blocks). "mode": "managed", // "type" is included for kind "resource" only, and specifies the resource // type. "type": "aws_instance", // "name" is the local name of the object. For a resource this is the // second label in the resource block header, and for an output value // this is the single label in the output block header. "name": "example", // "module" is included if the object belongs to a module other than // the root module, and provides an opaque string representation of the // module this object belongs to. This example is of a root module // resource and so "module" is not included. } // "status" is the aggregate status of all of the instances of the object // being described by this object. // The possible values are "pass", "fail", "error", and "unknown". "status": "fail", // "instances" describes the current status of each of the instances of // the object being described. An object can have multiple instances if // it is either a resource which has "count" or "for_each" set, or if // it's contained within a module that has "count" or "for_each" set. // // If "instances" is empty or omitted, that can either mean that the object // has no instances at all (e.g. count = 0) or that an error blocked // evaluation of the repetition argument. You can distinguish these cases // using the "status" property, which will be "pass" or "error" for a // zero-instance object and "unknown" for situations where an error blocked // evaluation. "instances": [ { // "address" is an object similar to the property of the same name in // the containing object. Merge the instance-level address into the // object-level address, overwriting any conflicting property names, // to create a full description of the instance's address. "address": { // "to_display" overrides the property of the same name in the main // object's address, to include any module instance or resource // instance keys that uniquely identify this instance. "to_display": "aws_instance.example[0]", // "instance_key" is included for resources only and specifies the // resource-level instance key, which can either be a number or a // string. Omitted for single-instance resources. "instance_key": 0, // "module" is included if the object belongs to a module other than // the root module, and provides an opaque string representation of the // module instance this object belongs to. }, // "status" describes the result of running the configured checks // against this particular instance of the object, with the same // possible values as the "status" in the parent object. // // "fail" means that the condition evaluated successfully but returned // false, while "error" means that the condition expression itself // was invalid. "status": "fail", // "problems" might be included for statuses "fail" or "error", in // which case it describes the individual conditions that failed for // this instance, if any. // When a condition expression is invalid, OpenTofu returns that as // a normal error message rather than as a problem in this list. "problems": [ { // "message" is the string that resulted from evaluating the // error_message argument of the failing condition. "message": "Server does not have a public IPv6 address." } ] }, ] }] The "checks" model includes both static checkable objects and instances of those objects to ensure that the set of checkable objects will be consistent even if an error prevents full evaluation of the configuration. Any object in the configuration which has associated checks, such as a resource with preconditions or postconditions, will always be included as a checkable object even if a runtime error prevents OpenTofu from evaluating its "count" or "for\_each" argument and therefore determining which instances of that object exist dynamically. When summarizing checks in a UI, we recommend preferring to list only the individual instances and typically ignoring the top-level objects altogether. However, in any case where an object has _zero_ instances, the UI should show the top-level object instead to serve as a placeholder so that the user can see that OpenTofu recognized the existence of the checks, even if it wasn't able to evaluate them on the most recent run. * [Format Summary](https://opentofu.org/docs/v1.10/internals/json-format/#format-summary) * [State Representation](https://opentofu.org/docs/v1.10/internals/json-format/#state-representation) * [Plan Representation](https://opentofu.org/docs/v1.10/internals/json-format/#plan-representation) * [Values Representation](https://opentofu.org/docs/v1.10/internals/json-format/#values-representation) * [Configuration Representation](https://opentofu.org/docs/v1.10/internals/json-format/#configuration-representation) * [Expression Representation](https://opentofu.org/docs/v1.10/internals/json-format/#expression-representation) * [Block Expressions Representation](https://opentofu.org/docs/v1.10/internals/json-format/#block-expressions-representation) * [Change Representation](https://opentofu.org/docs/v1.10/internals/json-format/#change-representation) * [Checks Representation](https://opentofu.org/docs/v1.10/internals/json-format/#checks-representation) --- # Files and Directories | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/files/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Files and Directories ===================== File Extension[​](https://opentofu.org/docs/v1.10/language/files/#file-extension "Direct link to File Extension") ------------------------------------------------------------------------------------------------------------------ Code in the OpenTofu language is stored in plain text files with the `.tf` or `.tofu` file extensions. There is also [a JSON-based variant of the language](https://opentofu.org/docs/v1.10/language/syntax/json/) that is named with the `.tf.json` or `.tofu.json` file extensions. Files containing OpenTofu code are often called _configuration files._ ### Extension Precedence[​](https://opentofu.org/docs/v1.10/language/files/#extension-precedence "Direct link to Extension Precedence") When both `.tf` and `.tofu` files with the same base name are present in a directory, OpenTofu will prioritize the `.tofu` file and ignore the `.tf` file. For example: * If both `foo.tf` and `foo.tofu` exist in the same directory, OpenTofu will only load `foo.tofu` and ignore `foo.tf`. This ensures that `.tofu` files always take precedence over `.tf` files when both are available. This scenario can be useful for module authors who want their modules to support both OpenTofu and Terraform. Text Encoding[​](https://opentofu.org/docs/v1.10/language/files/#text-encoding "Direct link to Text Encoding") --------------------------------------------------------------------------------------------------------------- Configuration files must always use UTF-8 encoding, and by convention usually use Unix-style line endings (LF) rather than Windows-style line endings (CRLF), though both are accepted. Directories and Modules[​](https://opentofu.org/docs/v1.10/language/files/#directories-and-modules "Direct link to Directories and Modules") --------------------------------------------------------------------------------------------------------------------------------------------- A _module_ is a collection of one or many `.tf`, `.tf.json`, `.tofu`, `.tofu.json` files kept together in a directory. An OpenTofu module only consists of the top-level configuration files in a directory; nested directories are treated as completely separate modules, and are not automatically included in the configuration. OpenTofu evaluates all of the configuration files in a module, effectively treating the entire module as a single document. Separating various blocks into different files is purely for the convenience of readers and maintainers, and has no effect on the module's behavior. An OpenTofu module can use [module calls](https://opentofu.org/docs/v1.10/language/modules/) to explicitly include other modules into the configuration. These child modules can come from local directories (nested in the parent module's directory, or anywhere else on disk), or from external sources like the [Public OpenTofu Registry](https://registry.opentofu.org/) . The Root Module[​](https://opentofu.org/docs/v1.10/language/files/#the-root-module "Direct link to The Root Module") --------------------------------------------------------------------------------------------------------------------- OpenTofu always runs in the context of a single _root module._ A complete _OpenTofu configuration_ consists of a root module and the tree of child modules (which includes the modules called by the root module, any modules called by those modules, etc.). * In OpenTofu CLI, the root module is the working directory where OpenTofu is invoked. (You can use command line options to specify a root module outside the working directory, but in practice this is rare.) * In [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software), the root module for a workspace defaults to the top level of the configuration directory (supplied via version control repository or direct upload), but the workspace settings can specify a subdirectory to use instead. * [File Extension](https://opentofu.org/docs/v1.10/language/files/#file-extension) * [Extension Precedence](https://opentofu.org/docs/v1.10/language/files/#extension-precedence) * [Text Encoding](https://opentofu.org/docs/v1.10/language/files/#text-encoding) * [Directories and Modules](https://opentofu.org/docs/v1.10/language/files/#directories-and-modules) * [The Root Module](https://opentofu.org/docs/v1.10/language/files/#the-root-module) --- # Data Sources | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/data-sources/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Data Sources ============ _Data sources_ allow OpenTofu to use information defined outside of OpenTofu, defined by another separate OpenTofu configuration, or modified by functions. Each [provider](https://opentofu.org/docs/v1.10/language/providers/) may offer data sources alongside its set of [resource](https://opentofu.org/docs/v1.10/language/resources/) types. Using Data Sources[​](https://opentofu.org/docs/v1.10/language/data-sources/#using-data-sources "Direct link to Using Data Sources") ------------------------------------------------------------------------------------------------------------------------------------- A data source is accessed via a special kind of resource known as a _data resource_, declared using a `data` block: Code Block data "aws_ami" "example" { most_recent = true owners = ["self"] tags = { Name = "app-server" Tested = "true" }} A `data` block requests that OpenTofu read from a given data source ("aws\_ami") and export the result under the given local name ("example"). The name is used to refer to this resource from elsewhere in the same OpenTofu module, but has no significance outside of the scope of a module. The data source and name together serve as an identifier for a given resource and so must be unique within a module. Within the block body (between `{` and `}`) are query constraints defined by the data source. Most arguments in this section depend on the data source, and indeed in this example `most_recent`, `owners` and `tags` are all arguments defined specifically for [the `aws_ami` data source](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) . When distinguishing from data resources, the primary kind of resource (as declared by a `resource` block) is known as a _managed resource_. Both kinds of resources take arguments and export attributes for use in configuration, but while managed resources cause OpenTofu to create, update, and delete infrastructure objects, data resources cause OpenTofu only to _read_ objects. For brevity, managed resources are often referred to just as "resources" when the meaning is clear from context. Data Source Arguments[​](https://opentofu.org/docs/v1.10/language/data-sources/#data-source-arguments "Direct link to Data Source Arguments") ---------------------------------------------------------------------------------------------------------------------------------------------- Each data resource is associated with a single data source, which determines the kind of object (or objects) it reads and what query constraint arguments are available. Each data source in turn belongs to a [provider](https://opentofu.org/docs/v1.10/language/providers/) , which is a plugin for OpenTofu that offers a collection of resource types and data sources that most often belong to a single cloud or on-premises infrastructure platform. Most of the items within the body of a `data` block are defined by and specific to the selected data source, and these arguments can make full use of [expressions](https://opentofu.org/docs/v1.10/language/expressions/) and other dynamic OpenTofu language features. However, there are some "meta-arguments" that are defined by OpenTofu itself and apply across all data sources. These arguments often have additional restrictions on what language features can be used with them, and are described in more detail in the following sections. Data Resource Behavior[​](https://opentofu.org/docs/v1.10/language/data-sources/#data-resource-behavior "Direct link to Data Resource Behavior") ------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu reads data resources during the planning phase when possible, but announces in the plan when it must defer reading resources until the apply phase to preserve the order of operations. OpenTofu defers reading data resources in the following situations: * At least one of the given arguments is a managed resource attribute or other value that OpenTofu cannot predict until the apply step. * The data resource depends directly on a managed resource that itself has planned changes in the current plan. * The data resource has [custom conditions](https://opentofu.org/docs/v1.10/language/data-sources/#custom-condition-checks) and it depends directly or indirectly on a managed resource that itself has planned changes in the current plan. Refer to [Data Resource Dependencies](https://opentofu.org/docs/v1.10/language/data-sources/#data-resource-dependencies) for details on what it means for a data resource to depend on other objects. Any resulting attribute of such a data resource will be unknown during planning, so it cannot be used in situations where values must be fully known. Local-only Data Sources[​](https://opentofu.org/docs/v1.10/language/data-sources/#local-only-data-sources "Direct link to Local-only Data Sources") ---------------------------------------------------------------------------------------------------------------------------------------------------- While many data sources correspond to an infrastructure object type that is accessed via a remote network API, some specialized data sources operate only within OpenTofu itself, calculating some results and exposing them for use elsewhere. For example, local-only data sources exist for [rendering templates](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) , [reading local files](https://registry.terraform.io/providers/hashicorp/local/latest/docs/data-sources/file) , and [rendering AWS IAM policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) . The behavior of local-only data sources is the same as all other data sources, but their result data exists only temporarily during an OpenTofu operation, and is re-calculated each time a new plan is created. Data Resource Dependencies[​](https://opentofu.org/docs/v1.10/language/data-sources/#data-resource-dependencies "Direct link to Data Resource Dependencies") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Data resources have the same dependency resolution behavior [as defined for managed resources](https://opentofu.org/docs/v1.10/language/resources/behavior/#resource-dependencies) . Setting the `depends_on` meta-argument within `data` blocks defers reading of the data source until after all changes to the dependencies have been applied. In order to ensure that data sources are accessing the most up to date information possible in a wide variety of use cases, arguments directly referencing managed resources are treated the same as if the resource was listed in `depends_on`. This behavior can be avoided when desired by indirectly referencing the managed resource values through a `local` value, unless the data resource itself has [custom conditions](https://opentofu.org/docs/v1.10/language/data-sources/#custom-condition-checks) . Custom Condition Checks[​](https://opentofu.org/docs/v1.10/language/data-sources/#custom-condition-checks "Direct link to Custom Condition Checks") ---------------------------------------------------------------------------------------------------------------------------------------------------- You can use `precondition` and `postcondition` blocks to specify assumptions and guarantees about how the data source operates. The following examples creates a postcondition that checks whether the AMI has the correct tags. Code Block data "aws_ami" "example" { id = var.aws_ami_id lifecycle { # The AMI ID must refer to an existing AMI that has the tag "nomad-server". postcondition { condition = self.tags["Component"] == "nomad-server" error_message = "tags[\"Component\"] must be \"nomad-server\"." } }} Custom conditions can help capture assumptions, helping future maintainers understand the configuration design and intent. They also return useful information about errors earlier and in context, helping consumers more easily diagnose issues in their configurations. Refer to [Custom Condition Checks](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#preconditions-and-postconditions) for more details. Multiple Resource Instances[​](https://opentofu.org/docs/v1.10/language/data-sources/#multiple-resource-instances "Direct link to Multiple Resource Instances") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Data resources support [`count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) and [`for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) meta-arguments as defined for managed resources, with the same syntax and behavior. As with managed resources, when `count` or `for_each` is present it is important to distinguish the resource itself from the multiple resource _instances_ it creates. Each instance will separately read from its data source with its own variant of the constraint arguments, producing an indexed result. Selecting a Non-default Provider Configuration[​](https://opentofu.org/docs/v1.10/language/data-sources/#selecting-a-non-default-provider-configuration "Direct link to Selecting a Non-default Provider Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Data resources support [the `provider` meta-argument](https://opentofu.org/docs/v1.10/language/meta-arguments/resource-provider/) as defined for managed resources, with the same syntax and behavior. Lifecycle Customizations[​](https://opentofu.org/docs/v1.10/language/data-sources/#lifecycle-customizations "Direct link to Lifecycle Customizations") ------------------------------------------------------------------------------------------------------------------------------------------------------- Data resources do not have any customization settings available for their lifecycle. However, the `lifecycle` block is reserved for future versions. Example[​](https://opentofu.org/docs/v1.10/language/data-sources/#example "Direct link to Example") ---------------------------------------------------------------------------------------------------- A data source configuration looks like the following: Code Block # Find the latest available AMI that is tagged with Component = webdata "aws_ami" "web" { filter { name = "state" values = ["available"] } filter { name = "tag:Component" values = ["web"] } most_recent = true} Description[​](https://opentofu.org/docs/v1.10/language/data-sources/#description "Direct link to Description") ---------------------------------------------------------------------------------------------------------------- The `data` block creates a data instance of the given _type_ (first block label) and _name_ (second block label). The combination of the type and name must be unique. Within the block (the `{ }`) is configuration for the data instance. The configuration is dependent on the type; as with [resources](https://opentofu.org/docs/v1.10/language/resources/) , each provider on the [Public OpenTofu Registry](https://registry.opentofu.org/) has its own documentation for configuring and using the data types it provides. Each data instance will export one or more attributes, which can be used in other resources as reference expressions of the form `data...`. For example: Code Block resource "aws_instance" "web" { ami = data.aws_ami.web.id instance_type = "t1.micro"} Meta-Arguments[​](https://opentofu.org/docs/v1.10/language/data-sources/#meta-arguments "Direct link to Meta-Arguments") ------------------------------------------------------------------------------------------------------------------------- As data sources are essentially a read only subset of resources, they also support the same [meta-arguments](https://opentofu.org/docs/v1.10/language/resources/syntax/#meta-arguments) of resources with the exception of the [`lifecycle` configuration block](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/) . ### Non-Default Provider Configurations[​](https://opentofu.org/docs/v1.10/language/data-sources/#non-default-provider-configurations "Direct link to Non-Default Provider Configurations") Similarly to [resources](https://opentofu.org/docs/v1.10/language/resources/) , when a module has multiple configurations for the same provider you can specify which configuration to use with the `provider` meta-argument: Code Block data "aws_ami" "web" { provider = aws.west # ...} See [The Resource `provider` Meta-Argument](https://opentofu.org/docs/v1.10/language/meta-arguments/resource-provider/) for more information. Data Source Lifecycle[​](https://opentofu.org/docs/v1.10/language/data-sources/#data-source-lifecycle "Direct link to Data Source Lifecycle") ---------------------------------------------------------------------------------------------------------------------------------------------- If the arguments of a data instance contain no references to computed values, such as attributes of resources that have not yet been created, then the data instance will be read and its state updated during OpenTofu's "refresh" phase, which by default runs prior to creating a plan. This ensures that the retrieved data is available for use during planning and the diff will show the real values obtained. Data instance arguments may refer to computed values, in which case the attributes of the instance itself cannot be resolved until all of its arguments are defined. In this case, refreshing the data instance will be deferred until the "apply" phase, and all interpolations of the data instance attributes will show as "computed" in the plan since the values are not yet known. * [Using Data Sources](https://opentofu.org/docs/v1.10/language/data-sources/#using-data-sources) * [Data Source Arguments](https://opentofu.org/docs/v1.10/language/data-sources/#data-source-arguments) * [Data Resource Behavior](https://opentofu.org/docs/v1.10/language/data-sources/#data-resource-behavior) * [Local-only Data Sources](https://opentofu.org/docs/v1.10/language/data-sources/#local-only-data-sources) * [Data Resource Dependencies](https://opentofu.org/docs/v1.10/language/data-sources/#data-resource-dependencies) * [Custom Condition Checks](https://opentofu.org/docs/v1.10/language/data-sources/#custom-condition-checks) * [Multiple Resource Instances](https://opentofu.org/docs/v1.10/language/data-sources/#multiple-resource-instances) * [Selecting a Non-default Provider Configuration](https://opentofu.org/docs/v1.10/language/data-sources/#selecting-a-non-default-provider-configuration) * [Lifecycle Customizations](https://opentofu.org/docs/v1.10/language/data-sources/#lifecycle-customizations) * [Example](https://opentofu.org/docs/v1.10/language/data-sources/#example) * [Description](https://opentofu.org/docs/v1.10/language/data-sources/#description) * [Meta-Arguments](https://opentofu.org/docs/v1.10/language/data-sources/#meta-arguments) * [Non-Default Provider Configurations](https://opentofu.org/docs/v1.10/language/data-sources/#non-default-provider-configurations) * [Data Source Lifecycle](https://opentofu.org/docs/v1.10/language/data-sources/#data-source-lifecycle) --- # Override Files | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/files/override/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Override Files ============== OpenTofu normally loads all of the `.tf`, `.tofu`, `.tf.json` and `.tofu.json` files within a directory and expects each one to define a distinct set of configuration objects. If two files attempt to define the same object, OpenTofu returns an error. In some rare cases, it is convenient to be able to override specific portions of an existing configuration object in a separate file. For example, a human-edited configuration file in the OpenTofu language native syntax could be partially overridden using a programmatically-generated file in JSON syntax. For these rare situations, OpenTofu has special handling of any configuration file whose name ends in `_override.tf`, `_override.tofu`, `_override.tf.json` or `_override.tofu.json`. This special handling also applies to a file named literally `override.tf`, `override.tofu`, `override.tf.json` or `override.tofu.json`. Note [Extension Precedence](https://opentofu.org/docs/v1.10/language/files/#extension-precedence) is important when dealing with override files. If both `foo_override.tf` and `foo_override.tofu` exist in the same directory, OpenTofu will only load `foo_override.tofu` and disregard `foo_override.tf`. The same rule applies to JSON-based files - if both `foo_override.tofu.json` and `foo_override.tf.json` exist in the same directory, OpenTofu will only load `foo_override.tofu.json` and ignore `foo_override.tf.json`. OpenTofu initially skips these _override files_ when loading configuration, and then afterwards processes each one in turn (in lexicographical order). For each top-level block defined in an override file, OpenTofu attempts to find an already-defined object corresponding to that block and then merges the override block contents into the existing object. Use override files only in special circumstances. Over-use of override files hurts readability, since a reader looking only at the original files cannot easily see that some portions of those files have been overridden without consulting all of the override files that are present. When using override files, use comments in the original files to warn future readers about which override files apply changes to each block. Example[​](https://opentofu.org/docs/v1.10/language/files/override/#example "Direct link to Example") ------------------------------------------------------------------------------------------------------ If you have an OpenTofu configuration `example.tf` with the following contents: Code Block resource "aws_instance" "web" { instance_type = "t2.micro" ami = "ami-408c7f28"} ...and you created a file `override.tf` containing the following: Code Block resource "aws_instance" "web" { ami = "foo"} OpenTofu will merge the latter into the former, behaving as if the original configuration had been as follows: Code Block resource "aws_instance" "web" { instance_type = "t2.micro" ami = "foo"} Merging Behavior[​](https://opentofu.org/docs/v1.10/language/files/override/#merging-behavior "Direct link to Merging Behavior") --------------------------------------------------------------------------------------------------------------------------------- The merging behavior is slightly different for each block type, and some special constructs within certain blocks are merged in a special way. The general rule, which applies in most cases, is: * A top-level block in an override file merges with a block in a normal configuration file that has the same block header. The block _header_ is the block type and any quoted labels that follow it. * Within a top-level block, an attribute argument within an override block replaces any argument of the same name in the original block. * Within a top-level block, any nested blocks within an override block replace _all_ blocks of the same type in the original block. Any block types that do not appear in the override block remain from the original block. * The contents of nested configuration blocks are not merged. * The resulting _merged block_ must still comply with any validation rules that apply to the given block type. If more than one override file defines the same top-level block, the overriding effect is compounded, with later blocks taking precedence over earlier blocks. Overrides are processed in order first by filename (in lexicographical order) and then by position in each file. The following sections describe the special merging behaviors that apply to specific arguments within certain top-level block types. ### Merging `resource` and `data` blocks[​](https://opentofu.org/docs/v1.10/language/files/override/#merging-resource-and-data-blocks "Direct link to merging-resource-and-data-blocks") Within a `resource` block, the contents of any `lifecycle` nested block are merged on an argument-by-argument basis. For example, if an override block sets only the `create_before_destroy` argument then any `ignore_changes` argument in the original block will be preserved. If an overriding `resource` block contains one or more `provisioner` blocks then any `provisioner` blocks in the original block are ignored. If an overriding `resource` block contains a `connection` block then it completely overrides any `connection` block present in the original block. The `depends_on` meta-argument may not be used in override blocks, and will produce an error. ### Merging `variable` blocks[​](https://opentofu.org/docs/v1.10/language/files/override/#merging-variable-blocks "Direct link to merging-variable-blocks") The arguments within a `variable` block are merged in the standard way described above, but some special considerations apply due to the interactions between the `type` and `default` arguments. If the original block defines a `default` value and an override block changes the variable's `type`, OpenTofu attempts to convert the default value to the overridden type, producing an error if this conversion is not possible. Conversely, if the original block defines a `type` and an override block changes the `default`, the overridden default value must be compatible with the original type specification. ### Merging `output` blocks[​](https://opentofu.org/docs/v1.10/language/files/override/#merging-output-blocks "Direct link to merging-output-blocks") The `depends_on` meta-argument may not be used in override blocks, and will produce an error. ### Merging `locals` blocks[​](https://opentofu.org/docs/v1.10/language/files/override/#merging-locals-blocks "Direct link to merging-locals-blocks") Each `locals` block defines a number of named values. Overrides are applied on a value-by-value basis, ignoring which `locals` block they are defined in. ### Merging `terraform` blocks[​](https://opentofu.org/docs/v1.10/language/files/override/#merging-terraform-blocks "Direct link to merging-terraform-blocks") The settings within `terraform` blocks are considered individually when merging. If the `required_providers` argument is set, its value is merged on an element-by-element basis, which allows an override block to adjust the constraint for a single provider without affecting the constraints for other providers. In both the `required_version` and `required_providers` settings, each override constraint entirely replaces the constraints for the same component in the original block. If both the base block and the override block both set `required_version` then the constraints in the base block are entirely ignored. The presence of a block defining a backend (either `cloud` or `backend`) in an override file always takes precedence over a block defining a backend in the original configuration. That is, if a `cloud` block is set within the original configuration and a `backend` block is set in the override file, OpenTofu will use the `backend` block specified in the override file upon merging. Similarly, if a `backend` block is set within the original configuration and a `cloud` block is set in the override file, OpenTofu will use the `cloud` block specified in the override file upon merging. * [Example](https://opentofu.org/docs/v1.10/language/files/override/#example) * [Merging Behavior](https://opentofu.org/docs/v1.10/language/files/override/#merging-behavior) * [Merging `resource` and `data` blocks](https://opentofu.org/docs/v1.10/language/files/override/#merging-resource-and-data-blocks) * [Merging `variable` blocks](https://opentofu.org/docs/v1.10/language/files/override/#merging-variable-blocks) * [Merging `output` blocks](https://opentofu.org/docs/v1.10/language/files/override/#merging-output-blocks) * [Merging `locals` blocks](https://opentofu.org/docs/v1.10/language/files/override/#merging-locals-blocks) * [Merging `terraform` blocks](https://opentofu.org/docs/v1.10/language/files/override/#merging-terraform-blocks) --- # Expressions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/expressions/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Expressions =========== _Expressions_ refer to or compute values within a configuration. The simplest expressions are just literal values, like `"hello"` or `5`, but the OpenTofu language also allows more complex expressions such as references to data exported by resources, arithmetic, conditional evaluation, and a number of built-in functions. Expressions can be used in a number of places in the OpenTofu language, but some contexts limit which expression constructs are allowed, such as requiring a literal value of a particular type or forbidding [references to resource attributes](https://opentofu.org/docs/v1.10/language/expressions/references/#references-to-resource-attributes) . Each language feature's documentation describes any restrictions it places on expressions. You can experiment with the behavior of OpenTofu's expressions from the OpenTofu expression console, by running [the `tofu console` command](https://opentofu.org/docs/v1.10/cli/commands/console/) . The other pages in this section describe the features of OpenTofu's expression syntax. * [Types and Values](https://opentofu.org/docs/v1.10/language/expressions/types/) documents the data types that OpenTofu expressions can resolve to, and the literal syntaxes for values of those types. * [Strings and Templates](https://opentofu.org/docs/v1.10/language/expressions/strings/) documents the syntaxes for string literals, including interpolation sequences and template directives. * [References to Values](https://opentofu.org/docs/v1.10/language/expressions/references/) documents how to refer to named values like variables and resource attributes. * [Operators](https://opentofu.org/docs/v1.10/language/expressions/operators/) documents the arithmetic, comparison, and logical operators. * [Function Calls](https://opentofu.org/docs/v1.10/language/expressions/function-calls/) documents the syntax for calling OpenTofu's built-in functions. * [Conditional Expressions](https://opentofu.org/docs/v1.10/language/expressions/conditionals/) documents the ` ? : ` expression, which chooses between two values based on a bool condition. * [For Expressions](https://opentofu.org/docs/v1.10/language/expressions/for/) documents expressions like `[for s in var.list : upper(s)]`, which can transform a complex type value into another complex type value. * [Splat Expressions](https://opentofu.org/docs/v1.10/language/expressions/splat/) documents expressions like `var.list[*].id`, which can extract simpler collections from more complicated expressions. * [Dynamic Blocks](https://opentofu.org/docs/v1.10/language/expressions/dynamic-blocks/) documents a way to create multiple repeatable nested blocks within a resource or other construct. * [Type Constraints](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/) documents the syntax for referring to a type, rather than a value of that type. Input variables expect this syntax in their `type` argument. * [Version Constraints](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/) documents the syntax of special strings that define a set of allowed software versions. OpenTofu uses version constraints in several places. --- # Conditional Expressions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/expressions/conditionals/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Conditional Expressions ======================= A _conditional expression_ uses the value of a boolean expression to select one of two values. Syntax[​](https://opentofu.org/docs/v1.10/language/expressions/conditionals/#syntax "Direct link to Syntax") ------------------------------------------------------------------------------------------------------------- The syntax of a conditional expression is as follows: Code Block condition ? true_val : false_val If `condition` is `true` then the result is `true_val`. If `condition` is `false` then the result is `false_val`. A common use of conditional expressions is to define defaults to replace invalid values: Code Block var.a != "" ? var.a : "default-a" If `var.a` is an empty string then the result is `"default-a"`, but otherwise it is the actual value of `var.a`. Conditions[​](https://opentofu.org/docs/v1.10/language/expressions/conditionals/#conditions "Direct link to Conditions") ------------------------------------------------------------------------------------------------------------------------- The condition can be any expression that resolves to a boolean value. This will usually be an expression that uses the equality, comparison, or logical operators. ### Custom Condition Checks[​](https://opentofu.org/docs/v1.10/language/expressions/conditionals/#custom-condition-checks "Direct link to Custom Condition Checks") You can create conditions that produce custom error messages for several types of objects in a configuration. For example, you can add a condition to an input variable that checks whether incoming image IDs are formatted properly. Custom conditions can help capture assumptions, helping future maintainers understand the configuration design and intent. They also return useful information about errors earlier and in context, helping consumers more easily diagnose issues in their configurations. Refer to [Custom Condition Checks](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#input-variable-validation) for details. Result Types[​](https://opentofu.org/docs/v1.10/language/expressions/conditionals/#result-types "Direct link to Result Types") ------------------------------------------------------------------------------------------------------------------------------- The two result values may be of any type, but they must both be of the _same_ type so that OpenTofu can determine what type the whole conditional expression will return without knowing the condition value. If the two result expressions don't produce the same type then OpenTofu will attempt to find a type that they can both convert to, and make those conversions automatically if so. For example, the following expression is valid and will always return a string, because in OpenTofu all numbers can convert automatically to a string using decimal digits: Code Block var.example ? 12 : "hello" Relying on this automatic conversion behavior can be confusing for those who are not familiar with OpenTofu's conversion rules though, so we recommend being explicit using type conversion functions in any situation where there may be some uncertainty about the expected result type. The following example is contrived because it would be easier to write the constant `"12"` instead of the type conversion in this case, but shows how to use [`tostring`](https://opentofu.org/docs/v1.10/language/functions/tostring/) to explicitly convert a number to a string. Code Block var.example ? tostring(12) : "hello" * [Syntax](https://opentofu.org/docs/v1.10/language/expressions/conditionals/#syntax) * [Conditions](https://opentofu.org/docs/v1.10/language/expressions/conditionals/#conditions) * [Custom Condition Checks](https://opentofu.org/docs/v1.10/language/expressions/conditionals/#custom-condition-checks) * [Result Types](https://opentofu.org/docs/v1.10/language/expressions/conditionals/#result-types) --- # Splat Expressions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/expressions/splat/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Splat Expressions ================= A _splat expression_ provides a more concise way to express a common operation that could otherwise be performed with a `for` expression. If `var.list` is a list of objects that all have an attribute `id`, then a list of the ids could be produced with the following `for` expression: Code Block [for o in var.list : o.id] This is equivalent to the following _splat expression:_ Code Block var.list[*].id The special `[*]` symbol iterates over all of the elements of the list given to its left and accesses from each one the attribute name given on its right. A splat expression can also be used to access attributes and indexes from lists of complex types by extending the sequence of operations to the right of the symbol: Code Block var.list[*].interfaces[0].name The above expression is equivalent to the following `for` expression: Code Block [for o in var.list : o.interfaces[0].name] Splat Expressions with Maps[​](https://opentofu.org/docs/v1.10/language/expressions/splat/#splat-expressions-with-maps "Direct link to Splat Expressions with Maps") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- The splat expression patterns shown above apply only to lists, sets, and tuples. To get a similar result with a map or object value you must use [`for` expressions](https://opentofu.org/docs/v1.10/language/expressions/for/) . Resources that use the `for_each` argument will appear in expressions as a map of objects, so you can't use splat expressions with those resources. For more information, see [Referring to Resource Instances](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#referring-to-instances) . Single Values as Lists[​](https://opentofu.org/docs/v1.10/language/expressions/splat/#single-values-as-lists "Direct link to Single Values as Lists") ------------------------------------------------------------------------------------------------------------------------------------------------------ Splat expressions have a special behavior when you apply them to a value that isn't a list, set, or tuple. If the value is anything other than a null value then the splat expression will transform it into a single-element list, or more accurately a single-element tuple value. If the value is _null_ then the splat expression will return an empty tuple. This special behavior can be useful for modules that accept optional input variables whose default value is `null` to represent the absence of any value. This allows the module to adapt the variable value for OpenTofu language features designed to work with collections. For example: Code Block variable "website_setting" { type = object({ index_document = string error_document = string }) default = null}resource "aws_s3_bucket" "example" { # ... dynamic "website" { for_each = var.website_setting[*] content { index_document = website.value.index_document error_document = website.value.error_document } }} The above example uses a [`dynamic` block](https://opentofu.org/docs/v1.10/language/expressions/dynamic-blocks/) , which generates zero or more nested blocks based on a collection value. The input variable `var.website_setting` is defined as a single object that might be null, so the `dynamic` block's `for_each` expression uses `[*]` to ensure that there will be one block if the module caller sets the website argument, or zero blocks if the caller leaves it set to null. This special behavior of splat expressions is not obvious to an unfamiliar reader, so we recommend using it only in `for_each` arguments and similar situations where the context implies working with a collection. Otherwise, the meaning of the expression may be unclear to future readers. Legacy (Attribute-only) Splat Expressions[​](https://opentofu.org/docs/v1.10/language/expressions/splat/#legacy-attribute-only-splat-expressions "Direct link to Legacy (Attribute-only) Splat Expressions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Earlier versions of the OpenTofu language had a slightly different version of splat expressions, which OpenTofu continues to support for backward compatibility. This older variant is less useful than the modern form described above, and so we recommend against using it in new configurations. The legacy "attribute-only" splat expressions use the sequence `.*`, instead of `[*]`: Code Block var.list.*.interfaces[0].name This form has a subtly different behavior, equivalent to the following `for` expression: Code Block [for o in var.list : o.interfaces][0].name Notice that with the attribute-only splat expression the index operation `[0]` is applied to the result of the iteration, rather than as part of the iteration itself. Only the attribute lookups apply to each element of the input. This limitation was confusing some people using older versions of OpenTofu and so we recommend always using the new-style splat expressions, with `[*]`, to get the more consistent behavior. * [Splat Expressions with Maps](https://opentofu.org/docs/v1.10/language/expressions/splat/#splat-expressions-with-maps) * [Single Values as Lists](https://opentofu.org/docs/v1.10/language/expressions/splat/#single-values-as-lists) * [Legacy (Attribute-only) Splat Expressions](https://opentofu.org/docs/v1.10/language/expressions/splat/#legacy-attribute-only-splat-expressions) --- # Arithmetic and Logical Operators | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/expressions/operators/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Arithmetic and Logical Operators ================================ An _operator_ is a type of expression that transforms or combines one or more other expressions. Operators either combine two values in some way to produce a third result value, or transform a single given value to produce a single result. Operators that work on two values place an operator symbol between the two values, similar to mathematical notation: `1 + 2`. Operators that work on only one value place an operator symbol before that value, like `!true`. The OpenTofu language has a set of operators for both arithmetic and logic, which are similar to operators in programming languages such as JavaScript or Ruby. When multiple operators are used together in an expression, they are evaluated in the following order of operations: 1. `!`, `-` (multiplication by `-1`) 2. `*`, `/`, `%` 3. `+`, `-` (subtraction) 4. `>`, `>=`, `<`, `<=` 5. `==`, `!=` 6. `&&` 7. `||` Use parentheses to override the default order of operations. Without parentheses, higher levels will be evaluated first, so OpenTofu will interpret `1 + 2 * 3` as `1 + (2 * 3)` and _not_ as `(1 + 2) * 3`. The different operators can be gathered into a few different groups with similar behavior, as described below. Each group of operators expects its given values to be of a particular type. OpenTofu will attempt to convert values to the required type automatically, or will produce an error message if automatic conversion is impossible. Arithmetic Operators[​](https://opentofu.org/docs/v1.10/language/expressions/operators/#arithmetic-operators "Direct link to Arithmetic Operators") ---------------------------------------------------------------------------------------------------------------------------------------------------- The arithmetic operators all expect number values and produce number values as results: * `a + b` returns the result of adding `a` and `b` together. * `a - b` returns the result of subtracting `b` from `a`. * `a * b` returns the result of multiplying `a` and `b`. * `a / b` returns the result of dividing `a` by `b`. * `a % b` returns the remainder of dividing `a` by `b`. This operator is generally useful only when used with whole numbers. * `-a` returns the result of multiplying `a` by `-1`. OpenTofu supports some other less-common numeric operations as [functions](https://opentofu.org/docs/v1.10/language/expressions/function-calls/) . For example, you can calculate exponents using [the `pow` function](https://opentofu.org/docs/v1.10/language/functions/pow/) . Equality Operators[​](https://opentofu.org/docs/v1.10/language/expressions/operators/#equality-operators "Direct link to Equality Operators") ---------------------------------------------------------------------------------------------------------------------------------------------- The equality operators both take two values of any type and produce boolean values as results. * `a == b` returns `true` if `a` and `b` both have the same type and the same value, or `false` otherwise. * `a != b` is the opposite of `a == b`. Because the equality operators require both arguments to be of exactly the same type in order to decide equality, we recommend using these operators only with values of primitive types or using explicit type conversion functions to indicate which type you are intending to use for comparison. Comparisons between structural types may produce surprising results if you are not sure about the types of each of the arguments. For example, `var.list == []` may seem like it would return `true` if `var.list` were an empty list, but `[]` actually builds a value of type `tuple([])` and so the two values can never match. In this situation it's often clearer to write `length(var.list) == 0` instead. Comparison Operators[​](https://opentofu.org/docs/v1.10/language/expressions/operators/#comparison-operators "Direct link to Comparison Operators") ---------------------------------------------------------------------------------------------------------------------------------------------------- The comparison operators all expect number values and produce boolean values as results. * `a < b` returns `true` if `a` is less than `b`, or `false` otherwise. * `a <= b` returns `true` if `a` is less than or equal to `b`, or `false` otherwise. * `a > b` returns `true` if `a` is greater than `b`, or `false` otherwise. * `a >= b` returns `true` if `a` is greater than or equal to `b`, or `false` otherwise. Logical Operators[​](https://opentofu.org/docs/v1.10/language/expressions/operators/#logical-operators "Direct link to Logical Operators") ------------------------------------------------------------------------------------------------------------------------------------------- The logical operators all expect bool values and produce bool values as results. * `a || b` returns `true` if either `a` or `b` is `true`, or `false` if both are `false`. * `a && b` returns `true` if both `a` and `b` are `true`, or `false` if either one is `false`. * `!a` returns `true` if `a` is `false`, and `false` if `a` is `true`. OpenTofu does not have an operator for the "exclusive OR" operation. If you know that both operators are boolean values then exclusive OR is equivalent to the `!=` ("not equal") operator. The logical operators in OpenTofu do not short-circuit, meaning `var.foo || var.foo.bar` will produce an error message if `var.foo` is `null` because both `var.foo` and `var.foo.bar` are evaluated. * [Arithmetic Operators](https://opentofu.org/docs/v1.10/language/expressions/operators/#arithmetic-operators) * [Equality Operators](https://opentofu.org/docs/v1.10/language/expressions/operators/#equality-operators) * [Comparison Operators](https://opentofu.org/docs/v1.10/language/expressions/operators/#comparison-operators) * [Logical Operators](https://opentofu.org/docs/v1.10/language/expressions/operators/#logical-operators) --- # Types and Values | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/expressions/types/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Types and Values ================ The result of an expression is a _value_. All values have a _type_, which dictates where that value can be used and what transformations can be applied to it. Types[​](https://opentofu.org/docs/v1.10/language/expressions/types/#types "Direct link to Types") --------------------------------------------------------------------------------------------------- The OpenTofu language uses the following types for its values: * `string`: a sequence of Unicode characters representing some text, like `"hello"`. * `number`: a numeric value. The `number` type can represent both whole numbers like `15` and fractional values like `6.283185`. * `bool`: a boolean value, either `true` or `false`. `bool` values can be used in conditional logic. * `list`: a sequence of values, like `["us-west-1a", "us-west-1c"]`. Elements in a list are identified by consecutive whole numbers, starting with zero. * `set`: a collection of unique values that do not have any secondary identifiers or ordering. * `map`: a group of values identified by named labels, like `{name = "Mabel", age = 52}`. Strings, numbers, and bools are sometimes called _primitive types._ Lists and sets are forms of tuples. Maps are a form of objects. Tuples and maps are sometimes called _complex types,_ _structural types,_ or _collection types._ See [Type Constraints](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/) for a more detailed description of complex types. Finally, there is one special value that has _no_ type: * `null`: a value that represents _absence_ or _omission._ If you set an argument of a resource to `null`, OpenTofu behaves as though you had completely omitted it β€”Β it will use the argument's default value if it has one, or raise an error if the argument is mandatory. `null` is most useful in conditional expressions, so you can dynamically omit an argument if a condition isn't met. Literal Expressions[​](https://opentofu.org/docs/v1.10/language/expressions/types/#literal-expressions "Direct link to Literal Expressions") --------------------------------------------------------------------------------------------------------------------------------------------- A _literal expression_ is an expression that directly represents a particular constant value. OpenTofu has a literal expression syntax for each of the value types described above. ### Strings[​](https://opentofu.org/docs/v1.10/language/expressions/types/#strings "Direct link to Strings") Strings are usually represented by a double-quoted sequence of Unicode characters, `"like this"`. There is also a "heredoc" syntax for more complex strings. String literals are the most complex kind of literal expression in OpenTofu, and have their own page of documentation. See [Strings](https://opentofu.org/docs/v1.10/language/expressions/strings/) for information about escape sequences, the heredoc syntax, interpolation, and template directives. ### Numbers[​](https://opentofu.org/docs/v1.10/language/expressions/types/#numbers "Direct link to Numbers") Numbers are represented by unquoted sequences of digits with or without a decimal point, like `15` or `6.283185`. ### Bools[​](https://opentofu.org/docs/v1.10/language/expressions/types/#bools "Direct link to Bools") Bools are represented by the unquoted symbols `true` and `false`. ### Null[​](https://opentofu.org/docs/v1.10/language/expressions/types/#null "Direct link to Null") The null value is represented by the unquoted symbol `null`. ### Lists/Tuples[​](https://opentofu.org/docs/v1.10/language/expressions/types/#liststuples "Direct link to Lists/Tuples") Lists/tuples are represented by a pair of square brackets containing a comma-separated sequence of values, like `["a", 15, true]`. List literals can be split into multiple lines for readability, but always require a comma between values. A comma after the final value is allowed, but not required. Values in a list can be arbitrary expressions. ### Maps/Objects[​](https://opentofu.org/docs/v1.10/language/expressions/types/#mapsobjects "Direct link to Maps/Objects") Maps/objects are represented by a pair of curly braces containing a series of ` = ` pairs: Code Block { name = "John" age = 52} Key/value pairs can be separated by either a comma or a line break. The values in a map can be arbitrary expressions. The keys in a map must be strings; they can be left unquoted if they are a valid [identifier](https://opentofu.org/docs/v1.10/language/syntax/configuration/#identifiers) , but must be quoted otherwise. You can use a non-literal string expression as a key by wrapping it in parentheses, like `(var.business_unit_tag_name) = "SRE"`. Indices and Attributes[​](https://opentofu.org/docs/v1.10/language/expressions/types/#indices-and-attributes "Direct link to Indices and Attributes") ------------------------------------------------------------------------------------------------------------------------------------------------------ Elements of list/tuple and map/object values can be accessed using the square-bracket index notation, like `local.list[3]`. The expression within the brackets must be a whole number for list and tuple values or a string for map and object values. Map/object attributes with names that are valid identifiers can also be accessed using the dot-separated attribute notation, like `local.object.attrname`. In cases where a map might contain arbitrary user-specified keys, we recommend using only the square-bracket index notation (`local.map["keyname"]`). More About Complex Types[​](https://opentofu.org/docs/v1.10/language/expressions/types/#more-about-complex-types "Direct link to More About Complex Types") ------------------------------------------------------------------------------------------------------------------------------------------------------------ In most situations, lists and tuples behave identically, as do maps and objects. Whenever the distinction isn't relevant, the OpenTofu documentation uses each pair of terms interchangeably (with a historical preference for "list" and "map"). However, module authors and provider developers should understand the differences between these similar types (and the related `set` type), since they offer different ways to restrict the allowed values for input variables and resource arguments. For complete details about these types (and an explanation of why the difference usually doesn't matter), see [Type Constraints](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/) . Type Conversion[​](https://opentofu.org/docs/v1.10/language/expressions/types/#type-conversion "Direct link to Type Conversion") --------------------------------------------------------------------------------------------------------------------------------- Expressions are most often used to set values for the arguments of resources and child modules. In these cases, the argument has an expected type and the given expression must produce a value of that type. Where possible, OpenTofu automatically converts values from one type to another in order to produce the expected type. If this isn't possible, OpenTofu will produce a type mismatch error and you must update the configuration with a more suitable expression. OpenTofu automatically converts number and bool values to strings when needed. It also converts strings to numbers or bools, as long as the string contains a valid representation of a number or bool value. * `true` converts to `"true"`, and vice-versa * `false` converts to `"false"`, and vice-versa * `15` converts to `"15"`, and vice-versa * [Types](https://opentofu.org/docs/v1.10/language/expressions/types/#types) * [Literal Expressions](https://opentofu.org/docs/v1.10/language/expressions/types/#literal-expressions) * [Strings](https://opentofu.org/docs/v1.10/language/expressions/types/#strings) * [Numbers](https://opentofu.org/docs/v1.10/language/expressions/types/#numbers) * [Bools](https://opentofu.org/docs/v1.10/language/expressions/types/#bools) * [Null](https://opentofu.org/docs/v1.10/language/expressions/types/#null) * [Lists/Tuples](https://opentofu.org/docs/v1.10/language/expressions/types/#liststuples) * [Maps/Objects](https://opentofu.org/docs/v1.10/language/expressions/types/#mapsobjects) * [Indices and Attributes](https://opentofu.org/docs/v1.10/language/expressions/types/#indices-and-attributes) * [More About Complex Types](https://opentofu.org/docs/v1.10/language/expressions/types/#more-about-complex-types) * [Type Conversion](https://opentofu.org/docs/v1.10/language/expressions/types/#type-conversion) --- # Dynamic Blocks | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/expressions/dynamic-blocks/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page `dynamic` Blocks ================ Within top-level block constructs like resources, expressions can usually be used only when assigning a value to an argument using the `name = expression` form. This covers many uses, but some resource types include repeatable _nested blocks_ in their arguments, which typically represent separate objects that are related to (or embedded within) the containing object: Code Block resource "aws_elastic_beanstalk_environment" "tfenvtest" { name = "tf-test-name" # can use expressions here setting { # but the "setting" block is always a literal block }} You can dynamically construct repeatable nested blocks like `setting` using a special `dynamic` block type, which is supported inside `resource`, `data`, `provider`, and `provisioner` blocks: Code Block resource "aws_elastic_beanstalk_environment" "tfenvtest" { name = "tf-test-name" application = "${aws_elastic_beanstalk_application.tftest.name}" solution_stack_name = "64bit Amazon Linux 2018.03 v2.11.4 running Go 1.12.6" dynamic "setting" { for_each = var.settings content { namespace = setting.value["namespace"] name = setting.value["name"] value = setting.value["value"] } }} A `dynamic` block acts much like a [`for` expression](https://opentofu.org/docs/v1.10/language/expressions/for/) , but produces nested blocks instead of a complex typed value. It iterates over a given complex value, and generates a nested block for each element of that complex value. * The label of the dynamic block (`"setting"` in the example above) specifies what kind of nested block to generate. * The `for_each` argument provides the complex value to iterate over. * The `iterator` argument (optional) sets the name of a temporary variable that represents the current element of the complex value. If omitted, the name of the variable defaults to the label of the `dynamic` block (`"setting"` in the example above). * The `labels` argument (optional) is a list of strings that specifies the block labels, in order, to use for each generated block. You can use the temporary iterator variable in this value. * The nested `content` block defines the body of each generated block. You can use the temporary iterator variable inside this block. Since the `for_each` argument accepts any collection or structural value, you can use a `for` expression or splat expression to transform an existing collection. The iterator object (`setting` in the example above) has two attributes: * `key` is the map key or list element index for the current element. If the `for_each` expression produces a _set_ value then `key` is identical to `value` and should not be used. * `value` is the value of the current element. A `dynamic` block can only generate arguments that belong to the resource type, data source, provider or provisioner being configured. It is _not_ possible to generate meta-argument blocks such as `lifecycle` and `provisioner` blocks, since OpenTofu must process these before it is safe to evaluate expressions. The `for_each` value must be a collection with one element per desired nested block. If you need to declare resource instances based on a nested data structure or combinations of elements from multiple data structures you can use OpenTofu expressions and functions to derive a suitable value. For some common examples of such situations, see the [`flatten`](https://opentofu.org/docs/v1.10/language/functions/flatten/) and [`setproduct`](https://opentofu.org/docs/v1.10/language/functions/setproduct/) functions. Multi-level Nested Block Structures[​](https://opentofu.org/docs/v1.10/language/expressions/dynamic-blocks/#multi-level-nested-block-structures "Direct link to Multi-level Nested Block Structures") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Some providers define resource types that include multiple levels of blocks nested inside one another. You can generate these nested structures dynamically when necessary by nesting `dynamic` blocks in the `content` portion of other `dynamic` blocks. For example, a module might accept a complex data structure like the following: Code Block variable "load_balancer_origin_groups" { type = map(object({ origins = set(object({ hostname = string })) }))} If you were defining a resource whose type expects a block for each origin group and then nested blocks for each origin within a group, you could ask OpenTofu to generate that dynamically using the following nested `dynamic` blocks: Code Block dynamic "origin_group" { for_each = var.load_balancer_origin_groups content { name = origin_group.key dynamic "origin" { for_each = origin_group.value.origins content { hostname = origin.value.hostname } } } } When using nested `dynamic` blocks it's particularly important to pay attention to the iterator symbol for each block. In the above example, `origin_group.value` refers to the current element of the outer block, while `origin.value` refers to the current element of the inner block. If a particular resource type defines nested blocks that have the same type name as one of their parents, you can use the `iterator` argument in each of `dynamic` blocks to choose a different iterator symbol that makes the two easier to distinguish. Best Practices for `dynamic` Blocks[​](https://opentofu.org/docs/v1.10/language/expressions/dynamic-blocks/#best-practices-for-dynamic-blocks "Direct link to best-practices-for-dynamic-blocks") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Overuse of `dynamic` blocks can make configuration hard to read and maintain, so we recommend using them only when you need to hide details in order to build a clean user interface for a re-usable module. Always write nested blocks out literally where possible. If you find yourself defining most or all of a `resource` block's arguments and nested blocks using directly-corresponding attributes from an input variable then that might suggest that your module is not creating a useful abstraction. It may be better for the calling module to define the resource itself then pass information about it into your module. For more information on this design tradeoff, see [When to Write a Module](https://opentofu.org/docs/v1.10/language/modules/develop/#when-to-write-a-module) and [Module Composition](https://opentofu.org/docs/v1.10/language/modules/develop/composition/) . * [Multi-level Nested Block Structures](https://opentofu.org/docs/v1.10/language/expressions/dynamic-blocks/#multi-level-nested-block-structures) * [Best Practices for `dynamic` Blocks](https://opentofu.org/docs/v1.10/language/expressions/dynamic-blocks/#best-practices-for-dynamic-blocks) --- # Dependency Lock File | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Dependency Lock File ==================== An OpenTofu configuration may refer to two different kinds of external dependency that come from outside of its own codebase: * [Providers](https://opentofu.org/docs/v1.10/language/providers/requirements/) , which are plugins for OpenTofu that extend it with support for interacting with various external systems. * [Modules](https://opentofu.org/docs/v1.10/language/modules/) , which allow splitting out groups of OpenTofu configuration constructs (written in the OpenTofu language) into reusable abstractions. Both of these dependency types can be published and updated independently from OpenTofu itself and from the configurations that depend on them. For that reason, OpenTofu must determine which versions of those dependencies are potentially compatible with the current configuration and which versions are currently selected for use. [Version constraints](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/) within the configuration itself determine which versions of dependencies are _potentially_ compatible, but after selecting a specific version of each dependency OpenTofu remembers the decisions it made in a _dependency lock file_ so that it can (by default) make the same decisions again in future. At present, the dependency lock file tracks only _provider_ dependencies. OpenTofu does not remember version selections for remote modules, and so OpenTofu will always select the newest available module version that meets the specified version constraints. You can use an _exact_ version constraint to ensure that OpenTofu will always select the same module version. Lock File Location[​](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#lock-file-location "Direct link to Lock File Location") ---------------------------------------------------------------------------------------------------------------------------------------------- The dependency lock file is a file that belongs to the configuration as a whole, rather than to each separate module in the configuration. For that reason OpenTofu creates it and expects to find it in your current working directory when you run OpenTofu, which is also the directory containing the `.tf` or `.tofu` files for the root module of your configuration. The lock file is always named `.terraform.lock.hcl`, and this name is intended to signify that it is a lock file for various items that OpenTofu caches in the `.terraform` subdirectory of your working directory. OpenTofu automatically creates or updates the dependency lock file each time you run [the `tofu init` command](https://opentofu.org/docs/v1.10/cli/commands/init/) . You should include this file in your version control repository so that you can discuss potential changes to your external dependencies via code review, just as you would discuss potential changes to your configuration itself. The dependency lock file uses the same low-level syntax as the main OpenTofu language, but the dependency lock file is not itself an OpenTofu language configuration file. It is named with the suffix `.hcl` instead of `.tf` or `.tofu` in order to signify that difference. Dependency Installation Behavior[​](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#dependency-installation-behavior "Direct link to Dependency Installation Behavior") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When `tofu init` is working on installing all of the providers needed for a configuration, OpenTofu considers both the version constraints in the configuration _and_ the version selections recorded in the lock file. If a particular provider has no existing recorded selection, OpenTofu will select the newest available version that matches the given version constraint, and then update the lock file to include that selection. If a particular provider already has a selection recorded in the lock file, OpenTofu will always re-select that version for installation, even if a newer version has become available. You can override that behavior by adding the `-upgrade` option when you run `tofu init`, in which case OpenTofu will disregard the existing selections and once again select the newest available version matching the version constraint. If a particular `tofu init` call makes changes to the lock file, OpenTofu will mention that as part of its output: Code Block OpenTofu has made some changes to the provider dependency selections recordedin the .terraform.lock.hcl file. Review those changes and commit them to yourversion control system if they represent changes you intended to make. When you see this message, you can use your version control system to [review the changes OpenTofu has proposed in the file](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#understanding-lock-file-changes) , and if they represent changes you made intentionally you can send the change through your team's usual code review process. ### Checksum verification[​](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#checksum-verification "Direct link to Checksum verification") OpenTofu will also verify that each package it installs matches at least one of the checksums it previously recorded in the lock file, if any, returning an error if none of the checksums match: Code Block Error: Failed to install providerError while installing hashicorp/azurerm v2.1.0: the current package forregistry.opentofu.org/hashicorp/azurerm 2.1.0 doesn't match any of thechecksums previously recorded in the dependency lock file. This checksum verification is intended to represent a _[trust on first use](https://en.wikipedia.org/wiki/Trust_on_first_use) _ approach. When you add a new provider for the first time you can verify it in whatever way you choose or any way you are required to by relevant regulations, and then trust that OpenTofu will raise an error if a future run of `tofu init` encounters a non-matching package for the same provider version. There are two special considerations with the "trust on first use" model: * If you install a provider from an origin registry which provides checksums that are signed with a cryptographic signature, OpenTofu will treat all of the signed checksums as valid as long as one checksum matches. The lock file will therefore include checksums for both the package you installed for your current platform _and_ any other packages that might be available for other platforms. In this case, the `tofu init` output will include the fingerprint of the key that signed the checksums, with a message like `(signed, key ID 0C0AF313E5FD9F80)`. You may wish to confirm that you trust the holder of the given key before committing the lock file containing the signed checksums, or to retrieve and verify the full set of available packages for the given provider version. * If you install a provider for the first time using an alternative installation method, such as a filesystem or network mirror, OpenTofu will not be able to verify the checksums for any platform other than the one where you ran `tofu init`, and so it will not record the checksums for other platforms and so the configuration will not be usable on any other platform. To avoid this problem you can pre-populate checksums for a variety of different platforms in your lock file using [the `tofu providers lock` command](https://opentofu.org/docs/v1.10/cli/commands/providers/lock/) , which will then allow future calls to `tofu init` to verify that the packages available in your chosen mirror match the official packages from the provider's origin registry. Understanding Lock File Changes[​](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#understanding-lock-file-changes "Direct link to Understanding Lock File Changes") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Because the dependency lock file is primarily maintained automatically by OpenTofu itself, rather than being updated manually by you or your team, your version control system may show you that the file has changed. There are a few different types of changes that OpenTofu can potentially make to your lock file, which you may need to understand in order to review the proposed changes. The following sections will describe these common situations. ### Dependency on a new provider[​](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#dependency-on-a-new-provider "Direct link to Dependency on a new provider") If you add a new entry to the [provider requirements](https://opentofu.org/docs/v1.10/language/providers/requirements/) for any module in your configuration, or if you add an external module that includes a new provider dependency itself, `tofu init` will respond to that by selecting the newest version of that provider which meets all of the version constraints in the configuration, and it will record its decision as a new `provider` block in the dependency lock file. Code Block --- .terraform.lock.hcl 2020-10-07 16:12:07.539570634 -0700+++ .terraform.lock.hcl 2020-10-07 16:12:15.267487237 -0700@@ -6,6 +6,26 @@ ] }+provider "registry.opentofu.org/hashicorp/azurerm" {+ version = "2.30.0"+ constraints = "~> 2.12"+ hashes = [+ "h1:FJwsuowaG5CIdZ0WQyFZH9r6kIJeRKts9+GcRsTz1+Y=",+ "h1:c/ntSXrDYM1mUir2KufijYebPcwKqS9CRGd3duDSGfY=",+ "h1:yre4Ph76g9H84MbuhZ2z5MuldjSA4FsrX6538O7PCcY=",+ "zh:04f0a50bb2ba92f3bea6f0a9e549ace5a4c13ef0cbb6975494cac0ef7d4acb43",+ "zh:2082e12548ebcdd6fd73580e83f626ed4ed13f8cdfd51205d8696ffe54f30734",+ "zh:246bcc449e9a92679fb30f3c0a77f05513886565e2dcc66b16c4486f51533064",+ "zh:24de3930625ac9014594d79bfa42d600eca65e9022b9668b54bfd0d924e21d14",+ "zh:2a22893a576ff6f268d9bf81cf4a56406f7ba79f77826f6df51ee787f6d2840a",+ "zh:2b27485e19c2aaa9f15f29c4cff46154a9720647610171e30fc6c18ddc42ec28",+ "zh:435f24ce1fb2b63f7f02aa3c84ac29c5757cd29ec4d297ed0618423387fe7bd4",+ "zh:7d99725923de5240ff8b34b5510569aa4ebdc0bdb27b7bac2aa911a8037a3893",+ "zh:7e3b5d0af3b7411dd9dc65ec9ab6caee8c191aee0fa7f20fc4f51716e67f50c0",+ "zh:da0af4552bef5a29b88f6a0718253f3bf71ce471c959816eb7602b0dadb469ca",+ ]+}+ provider "registry.opentofu.org/newrelic/newrelic" { version = "2.1.2" constraints = "~> 2.1.1" The new lock file entry records several pieces of information: * `version`: the exact version that OpenTofu selected based on the version constraints in the configuration. * `constraints`: all of the version constraints that OpenTofu considered when making this selection. (OpenTofu doesn't actually use this information to make installation decisions, but includes it to help explain to human readers how the previous decision was made.) * `hashes`: a number of checksums that are all considered to be valid for packages implementing the selected version of this provider on different platforms. The meaning of these hashes is explained more under _[New provider package checksums](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#new-provider-package-checksums) _ below. ### New version of an existing provider[​](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#new-version-of-an-existing-provider "Direct link to New version of an existing provider") If you run `tofu init -upgrade` to ask OpenTofu to consider newer provider versions that still match the configured version constraints, OpenTofu may then select a newer version for a provider and update its existing `provider` block to reflect that change. Code Block --- .terraform.lock.hcl 2020-10-07 16:44:25.819579509 -0700+++ .terraform.lock.hcl 2020-10-07 16:43:42.785665945 -0700@@ -7,22 +7,22 @@ } provider "registry.opentofu.org/hashicorp/azurerm" {- version = "2.1.0"- constraints = "~> 2.1.0"+ version = "2.0.0"+ constraints = "2.0.0" hashes = [- "h1:EOJImaEaVThWasdqnJjfYc6/P8N/MRAq1J7avx5ZbV4=",- "zh:0015b491cf9151235e57e35ea6b89381098e61bd923f56dffc86026d58748880",- "zh:4c5682ba1e0fc7e2e602d3f103af1638f868c31fe80cc1a884a97f6dad6e1c11",- "zh:57bac885b108c91ade4a41590062309c832c9ab6bf6a68046161636fcaef1499",- "zh:5810d48f574c0e363c969b3f45276369c8f0a35b34d6202fdfceb7b85b3ac597",- "zh:5c6e37a44462b8662cf9bdd29ce30523712a45c27c5d4711738705be0785db41",- "zh:64548940a3387aa3a752e709ee9eb9982fa820fe60eb60e5f212cc1d2c58549e",- "zh:7f46749163da17330bbb5293dc825333c86304baa0a7c6256650ac536b4567c8",- "zh:8f8970f2df75ac43ffdd112055ee069d8bd1030f7eb4367cc4cf494a1fa802c3",- "zh:9ad693d00dc5d7d455d06faba70e716bce727c6706f7293288e87fd7956b8fe0",- "zh:b6e3cb55e6aec62b47edd0d2bd5e14bd6a2bcfdac65930a6e9e819934734c57b",- "zh:d6a3f3b9b05c28ecf3919e9e7afa185805a6d7442fc4b3eedba749c2731d1f0e",- "zh:d81fb624a357c57c7ea457ce543d865b39b12f26c2edd58a2f7cd43326c91010",+ "h1:bigGXBoRbp7dv79bEEn+aaju8575qEXHQ57XHVPJeB8=",+ "zh:09c603c8904ca4a5bc19e82335afbc2837dcc4bee81e395f9daccef2f2cba1c8",+ "zh:194a919d4836d6c6d4ce598d0c66cce00ddc0d0b5c40d01bb32789964d818b42",+ "zh:1f269627df4e266c4e0ef9ee2486534caa3c8bea91a201feda4bca525005aa0a",+ "zh:2bae3071bd5f8e553355c4b3a547d6efe1774a828142b762e9a4e85f79be7f63",+ "zh:6c98dfa5c3468e8d02e2b3af7c4a8a14a5d469ce5a642909643b413a17ca338b",+ "zh:7af78f61666fd45fbf428161c061ea2623162d601b79dc71d6a5158756853ffa",+ "zh:883c2df86ae9ba2a5c167cf5c2c7deca0239171a224d6d335f0fd6dd9c283830",+ "zh:a2028379078577d8ff5ecfca6e8a8b25a25ffb1686de0ee52a7fe8011783488b",+ "zh:abe6ef399552fd3861a454a839cd978c1d15735658fdc00f9054435aff0f4620",+ "zh:c30b1bf14077913c3cdf34979b1434dbb1353cb5995eb3956b191c50538b64a9",+ "zh:ca64ae2ad9793e5631e3b0b9327f7cb22cb5d8e9de57be7d85821791b1d5a375",+ "zh:fffe56904a38109bb8d613b02808a177c3ddfac19f03b3aac799281fea38f475", ] } The primary effect of selecting a new provider version is to change the value of `version` in the `provider` block. If the upgrade came along with a change to the configured version constraints, OpenTofu will also record that change in the `constraints` value. Because each version has its own set of distribution packages, switching to a new version will also tend to replace all of the values in `hashes`, to reflect the checksums of the packages for the new version. ### New provider package checksums[​](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#new-provider-package-checksums "Direct link to New provider package checksums") A more subtle change you may see in a `provider` block is the addition of new checksums that were not previously recorded, even though nothing else in the `provider` block has changed: Code Block --- .terraform.lock.hcl 2020-10-07 17:24:23.397892140 -0700+++ .terraform.lock.hcl 2020-10-07 17:24:57.423130253 -0700@@ -10,6 +10,7 @@ version = "2.1.0" constraints = "~> 2.1.0" hashes = [+ "h1:1xvaS5D8B8t6J6XmXxX8spo97tAzjhacjedFX1B47Fk=", "h1:EOJImaEaVThWasdqnJjfYc6/P8N/MRAq1J7avx5ZbV4=", "zh:0015b491cf9151235e57e35ea6b89381098e61bd923f56dffc86026d58748880", "zh:4c5682ba1e0fc7e2e602d3f103af1638f868c31fe80cc1a884a97f6dad6e1c11",\ \ The addition of a new checksum into the `hashes` value represents OpenTofu gradually transitioning between different _hashing schemes_. The `h1:` and `zh:` prefixes on these values represent different hashing schemes, each of which represents calculating a checksum using a different algorithm. We may occasionally introduce new hashing schemes if we learn of limitations in the existing schemes or if a new scheme offers some considerable additional benefit.\ \ The two hashing schemes currently supported are:\ \ * `zh:`: a mnemonic for "zip hash", this is a legacy hash format which is part of the OpenTofu provider registry protocol and is therefore used for providers that you install directly from an origin registry.\ \ This hashing scheme captures a SHA256 hash of each of the official `.zip` packages indexed in the origin registry. This is an effective scheme for verifying the official release packages when installed from a registry, but it's not suitable for verifying packages that come from other [provider installation methods](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation)\ , such as filesystem mirrors using the unpacked directory layout.\ \ * `h1:`: a mnemonic for "hash scheme 1", which is the current preferred hashing scheme.\ \ Hash scheme 1 is also a SHA256 hash, but is one computed from the _contents_ of the provider distribution package, rather than of the `.zip` archive it's contained within. This scheme therefore has the advantage that it can be calculated for an official `.zip` file, an unpacked directory with the same contents, or a recompressed `.zip` file which contains the same files but potentially different metadata or compression schemes.\ \ Due to the limited scope of the `zh:` scheme, OpenTofu will opportunistically add in the corresponding `h1:` checksums as it learns of them, which is what caused the addition of a second `h1:` checksum in the example change shown above.\ \ \ OpenTofu will add a new hash to an existing provider only if the hash is calculated from a package that _also_ matches one of the existing hashes. In the above example, OpenTofu installed a `hashicorp/azurerm` package for a different platform than that which produced the original `h1:` checksum, but was able to match it against one of the `zh:` checksums recorded previously. After confirming the `zh:` checksum match, OpenTofu then recorded the corresponding `h1:` checksum in order to gradually migrate from the old scheme to the new scheme.\ \ When installing a particular provider for the first time (where there is no existing `provider` block for it), OpenTofu will pre-populate the `hashes` value with any checksums that are covered by the provider developer's cryptographic signature, which usually covers all of the available packages for that provider version across all supported platforms. However, because the provider registry protocol still uses the `zh:` scheme, the initial set will consist primarily of hashes using that scheme, which OpenTofu will then upgrade opportunistically as you install the packages on different platforms.\ \ If you wish to avoid ongoing additions of new `h1:` hashes as you work with your configuration on new target platforms, or if you are installing providers from a mirror that therefore can't provide official signed checksums, you can ask OpenTofu to pre-populate hashes for a chosen set of platforms using [the `tofu providers lock` command](https://opentofu.org/docs/v1.10/cli/commands/providers/lock/)\ :\ \ Code Block\ \ tofu providers lock \ -platform=linux_arm64 \ -platform=linux_amd64 \ -platform=darwin_amd64 \ -platform=windows_amd64\ \ The above command will download and verify the official packages for all of the required providers across all four of the given platforms, and then record both `zh:` and `h1:` checksums for each of them in the lock file, thus avoiding the case where OpenTofu will learn about a `h1:` equivalent only at a later time. See the `tofu providers lock` documentation for more information on this command.\ \ ### Providers that are no longer required[​](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#providers-that-are-no-longer-required "Direct link to Providers that are no longer required")\ \ To determine whether there still exists a dependency on a given provider, OpenTofu uses two sources of truth: the configuration itself, and the state. If you remove the last dependency on a particular provider from both your configuration and state, then `tofu init` will remove any existing lock file entry for that provider.\ \ Code Block\ \ --- .terraform.lock.hcl 2020-10-07 16:12:07.539570634 -0700+++ .terraform.lock.hcl 2020-10-07 16:12:15.267487237 -0700@@ -6,26 +6,6 @@ ] }-provider "registry.opentofu.org/hashicorp/azurerm" {- version = "2.30.0"- constraints = "~> 2.12"- hashes = [- "h1:FJwsuowaG5CIdZ0WQyFZH9r6kIJeRKts9+GcRsTz1+Y=",- "h1:c/ntSXrDYM1mUir2KufijYebPcwKqS9CRGd3duDSGfY=",- "h1:yre4Ph76g9H84MbuhZ2z5MuldjSA4FsrX6538O7PCcY=",- "zh:04f0a50bb2ba92f3bea6f0a9e549ace5a4c13ef0cbb6975494cac0ef7d4acb43",- "zh:2082e12548ebcdd6fd73580e83f626ed4ed13f8cdfd51205d8696ffe54f30734",- "zh:246bcc449e9a92679fb30f3c0a77f05513886565e2dcc66b16c4486f51533064",- "zh:24de3930625ac9014594d79bfa42d600eca65e9022b9668b54bfd0d924e21d14",- "zh:2a22893a576ff6f268d9bf81cf4a56406f7ba79f77826f6df51ee787f6d2840a",- "zh:2b27485e19c2aaa9f15f29c4cff46154a9720647610171e30fc6c18ddc42ec28",- "zh:435f24ce1fb2b63f7f02aa3c84ac29c5757cd29ec4d297ed0618423387fe7bd4",- "zh:7d99725923de5240ff8b34b5510569aa4ebdc0bdb27b7bac2aa911a8037a3893",- "zh:7e3b5d0af3b7411dd9dc65ec9ab6caee8c191aee0fa7f20fc4f51716e67f50c0",- "zh:da0af4552bef5a29b88f6a0718253f3bf71ce471c959816eb7602b0dadb469ca",- ]-}- provider "registry.opentofu.org/newrelic/newrelic" { version = "2.1.2" constraints = "~> 2.1.1" If you add a new requirement for the same provider at a later date and run `tofu init` again, OpenTofu will treat it as if it were [an entirely new provider](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#dependency-on-a-new-provider) and so will not necessarily select the same version that was previously selected and will not be able to verify that the checksums remained unchanged. * [Lock File Location](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#lock-file-location) * [Dependency Installation Behavior](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#dependency-installation-behavior) * [Checksum verification](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#checksum-verification) * [Understanding Lock File Changes](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#understanding-lock-file-changes) * [Dependency on a new provider](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#dependency-on-a-new-provider) * [New version of an existing provider](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#new-version-of-an-existing-provider) * [New provider package checksums](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#new-provider-package-checksums) * [Providers that are no longer required](https://opentofu.org/docs/v1.10/language/files/dependency-lock/#providers-that-are-no-longer-required) --- # For Expressions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/expressions/for/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page `for` Expressions ================= A _`for` expression_ creates a complex type value by transforming another complex type value. Each element in the input value can correspond to either one or zero values in the result, and an arbitrary expression can be used to transform each input element into an output element. For example, if `var.list` were a list of strings, then the following expression would produce a tuple of strings with all-uppercase letters: Code Block [for s in var.list : upper(s)] This `for` expression iterates over each element of `var.list`, and then evaluates the expression `upper(s)` with `s` set to each respective element. It then builds a new tuple value with all of the results of executing that expression in the same order. Input Types[​](https://opentofu.org/docs/v1.10/language/expressions/for/#input-types "Direct link to Input Types") ------------------------------------------------------------------------------------------------------------------- A `for` expression's input (given after the `in` keyword) can be a list, a set, a tuple, a map, or an object. The above example showed a `for` expression with only a single temporary symbol `s`, but a `for` expression can optionally declare a pair of temporary symbols in order to use the key or index of each item too: Code Block [for k, v in var.map : length(k) + length(v)] For a map or object type, like above, the `k` symbol refers to the key or attribute name of the current element. You can also use the two-symbol form with lists and tuples, in which case the additional symbol is the index of each element starting from zero, which conventionally has the symbol name `i` or `idx` unless it's helpful to choose a more specific name: Code Block [for i, v in var.list : "${i} is ${v}"] The index or key symbol is always optional. If you specify only a single symbol after the `for` keyword then that symbol will always represent the _value_ of each element of the input collection. Result Types[​](https://opentofu.org/docs/v1.10/language/expressions/for/#result-types "Direct link to Result Types") ---------------------------------------------------------------------------------------------------------------------- The type of brackets around the `for` expression decide what type of result it produces. The above example uses `[` and `]`, which produces a tuple. If you use `{` and `}` instead, the result is an object and you must provide two result expressions that are separated by the `=>` symbol: Code Block {for s in var.list : s => upper(s)} This expression produces an object whose attributes are the original elements from `var.list` and their corresponding values are the uppercase versions. For example, the resulting value might be as follows: Code Block { foo = "FOO" bar = "BAR" baz = "BAZ"} A `for` expression alone can only produce either an object value or a tuple value, but OpenTofu's automatic type conversion rules mean that you can typically use the results in locations where lists, maps, and sets are expected. Filtering Elements[​](https://opentofu.org/docs/v1.10/language/expressions/for/#filtering-elements "Direct link to Filtering Elements") ---------------------------------------------------------------------------------------------------------------------------------------- A `for` expression can also include an optional `if` clause to filter elements from the source collection, producing a value with fewer elements than the source value: Code Block [for s in var.list : upper(s) if s != ""] One common reason for filtering collections in `for` expressions is to split a single source collection into two separate collections based on some criteria. For example, if the input `var.users` is a map of objects where the objects each have an attribute `is_admin` then you may wish to produce separate maps with admin vs non-admin objects: Code Block variable "users" { type = map(object({ is_admin = bool }))}locals { admin_users = { for name, user in var.users : name => user if user.is_admin } regular_users = { for name, user in var.users : name => user if !user.is_admin }} Element Ordering[​](https://opentofu.org/docs/v1.10/language/expressions/for/#element-ordering "Direct link to Element Ordering") ---------------------------------------------------------------------------------------------------------------------------------- Because `for` expressions can convert from unordered types (maps, objects, sets) to ordered types (lists, tuples), OpenTofu must choose an implied ordering for the elements of an unordered collection. For maps and objects, OpenTofu sorts the elements by key or attribute name, using lexical sorting. For sets of strings, OpenTofu sorts the elements by their value, using lexical sorting. For sets of other types, OpenTofu uses an arbitrary ordering that may change in future versions. We recommend converting the expression result into a set to make it clear elsewhere in the configuration that the result is unordered. You can use [the `toset` function](https://opentofu.org/docs/v1.10/language/functions/toset/) to concisely convert a `for` expression result to be of a set type. Code Block toset([for e in var.set : e.example]) Grouping Results[​](https://opentofu.org/docs/v1.10/language/expressions/for/#grouping-results "Direct link to Grouping Results") ---------------------------------------------------------------------------------------------------------------------------------- If the result type is an object (using `{` and `}` delimiters) then normally the given key expression must be unique across all elements in the result, or OpenTofu will return an error. Sometimes the resulting keys are _not_ unique, and so to support that situation OpenTofu supports a special _grouping mode_ which changes the result to support multiple elements per key. To activate grouping mode, add the symbol `...` after the value expression. For example: Code Block variable "users" { type = map(object({ role = string }))}locals { users_by_role = { for name, user in var.users : user.role => name... }} The above represents a situation where a module expects a map describing various users who each have a single "role", where the map keys are usernames. The usernames are guaranteed unique because they are map keys in the input, but many users may all share a single role name. The `local.users_by_role` expression inverts the input map so that the keys are the role names and the values are usernames, but the expression is in grouping mode (due to the `...` after `name`) and so the result will be a map of lists of strings, such as the following: Code Block { "admin": [ "ps", ], "maintainer": [ "am", "jb", "kl", "ma", ], "viewer": [ "st", "zq", ],} Due to [the element ordering rules](https://opentofu.org/docs/v1.10/language/expressions/for/#element-ordering) , OpenTofu will sort the users lexically by username as part of evaluating the `for` expression, and so the usernames associated with each role will be lexically sorted after grouping. Repeated Configuration Blocks[​](https://opentofu.org/docs/v1.10/language/expressions/for/#repeated-configuration-blocks "Direct link to Repeated Configuration Blocks") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The `for` expressions mechanism is for constructing collection values from other collection values within expressions, which you can then assign to individual resource arguments that expect complex values. Some resource types also define _nested block types_, which typically represent separate objects that belong to the containing resource in some way. You can't dynamically generate nested blocks using `for` expressions, but you _can_ generate nested blocks for a resource dynamically using [`dynamic` blocks](https://opentofu.org/docs/v1.10/language/expressions/dynamic-blocks/) . * [Input Types](https://opentofu.org/docs/v1.10/language/expressions/for/#input-types) * [Result Types](https://opentofu.org/docs/v1.10/language/expressions/for/#result-types) * [Filtering Elements](https://opentofu.org/docs/v1.10/language/expressions/for/#filtering-elements) * [Element Ordering](https://opentofu.org/docs/v1.10/language/expressions/for/#element-ordering) * [Grouping Results](https://opentofu.org/docs/v1.10/language/expressions/for/#grouping-results) * [Repeated Configuration Blocks](https://opentofu.org/docs/v1.10/language/expressions/for/#repeated-configuration-blocks) --- # Strings and Templates | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/expressions/strings/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Strings and Templates ===================== String literals are the most complex kind of literal expression in OpenTofu, and also the most commonly used. OpenTofu supports both a quoted syntax and a "heredoc" syntax for strings. Both of these syntaxes support template sequences for interpolating values and manipulating text. Quoted Strings[​](https://opentofu.org/docs/v1.10/language/expressions/strings/#quoted-strings "Direct link to Quoted Strings") -------------------------------------------------------------------------------------------------------------------------------- A quoted string is a series of characters delimited by straight double-quote characters (`"`). Code Block "hello" ### Escape Sequences[​](https://opentofu.org/docs/v1.10/language/expressions/strings/#escape-sequences "Direct link to Escape Sequences") In quoted strings, the backslash character serves as an escape sequence, with the following characters selecting the escape behavior: | Sequence | Replacement | | --- | --- | | `\n` | Newline | | `\r` | Carriage Return | | `\t` | Tab | | `\"` | Literal quote (without terminating the string) | | `\\` | Literal backslash | | `\uNNNN` | Unicode character from the basic multilingual plane (NNNN is four hex digits) | | `\UNNNNNNNN` | Unicode character from supplementary planes (NNNNNNNN is eight hex digits) | There are also two special escape sequences that do not use backslashes: | Sequence | Replacement | | --- | --- | | `$${` | Literal `${`, without beginning an interpolation sequence. | | `%%{` | Literal `%{`, without beginning a template directive sequence. | Heredoc Strings[​](https://opentofu.org/docs/v1.10/language/expressions/strings/#heredoc-strings "Direct link to Heredoc Strings") ----------------------------------------------------------------------------------------------------------------------------------- OpenTofu also supports a "heredoc" style of string literal inspired by Unix shell languages, which allows multi-line strings to be expressed more clearly. Code Block <}`/`%{else}`/`%{endif}` directive chooses between two templates based on the value of a bool expression: Code Block "Hello, %{ if var.name != "" }${var.name}%{ else }unnamed%{ endif }!" The `else` portion may be omitted, in which case the result is an empty string if the condition expression returns `false`. * The `%{for in }` / `%{endfor}` directive iterates over the elements of a given collection or structural value and evaluates a given template once for each element, concatenating the results together: Code Block <(, ) The function name specifies which function to call. Each defined function expects a specific number of arguments with specific value types, and returns a specific value type as a result. Some functions take an arbitrary number of arguments. For example, the `min` function takes any amount of number arguments and returns the one that is numerically smallest: Code Block min(55, 3453, 2) A function call expression evaluates to the function's return value. Available Functions[​](https://opentofu.org/docs/v1.10/language/expressions/function-calls/#available-functions "Direct link to Available Functions") ------------------------------------------------------------------------------------------------------------------------------------------------------ For a full list of available functions, see [the function reference](https://opentofu.org/docs/v1.10/language/functions/) . Expanding Function Arguments[​](https://opentofu.org/docs/v1.10/language/expressions/function-calls/#expanding-function-arguments "Direct link to Expanding Function Arguments") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If the arguments to pass to a function are available in a list or tuple value, that value can be _expanded_ into separate arguments. Provide the list value as an argument and follow it with the `...` symbol: Code Block min([55, 2453, 2]...) The expansion symbol is three periods (`...`), not a Unicode ellipsis character (`…`). Expansion is a special syntax that is only available in function calls. Using Sensitive Data as Function Arguments[​](https://opentofu.org/docs/v1.10/language/expressions/function-calls/#using-sensitive-data-as-function-arguments "Direct link to Using Sensitive Data as Function Arguments") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When using sensitive data, such as [an input variable](https://opentofu.org/docs/v1.10/language/values/variables/#suppressing-values-in-cli-output) or [an output defined](https://opentofu.org/docs/v1.10/language/values/outputs/#sensitive-suppressing-values-in-cli-output) as sensitive as function arguments, the sensitive information in the arguments will be tracked during the function call. For example, passing an object containing a sensitive input variable to the `keys()` function will return a list with all keys we expected, but the `values()` function will result in a list with first item as sensitive, because the value of key "a" is sensitive. Code Block > local.baz{ "a" = (sensitive value) "b" = "dog"}> keys(local.baz)[ "a", "b",]> values(local.baz)[ (sensitive value), "dog",] When OpenTofu Calls Functions[​](https://opentofu.org/docs/v1.10/language/expressions/function-calls/#when-opentofu-calls-functions "Direct link to When OpenTofu Calls Functions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Most of OpenTofu's built-in functions are, in programming language terms, [pure functions](https://en.wikipedia.org/wiki/Pure_function) . This means that their result is based only on their arguments and so it doesn't make any practical difference when OpenTofu would call them. However, a small subset of functions interact with outside state and so for those it can be helpful to know when OpenTofu will call them in relation to other events that occur in an OpenTofu run. The small set of special functions includes [`file`](https://opentofu.org/docs/v1.10/language/functions/file/) , [`templatefile`](https://opentofu.org/docs/v1.10/language/functions/templatefile/) , [`timestamp`](https://opentofu.org/docs/v1.10/language/functions/timestamp/) , and [`uuid`](https://opentofu.org/docs/v1.10/language/functions/uuid/) . If you are not working with these functions then you don't need to read this section, although the information here may still be interesting background information. The `file` and `templatefile` functions are intended for reading files that are included as a static part of the configuration and so OpenTofu will execute these functions as part of initial configuration validation, before taking any other actions with the configuration. That means you cannot use either function to read files that your configuration might generate dynamically on disk as part of the plan or apply steps. The `timestamp` function returns a representation of the current system time at the point when OpenTofu calls it, and the `uuid` function returns a random result which differs on each call. Without any special behavior, these would both cause the final configuration during the apply step not to match the actions shown in the plan, which violates the OpenTofu execution model. For that reason, OpenTofu arranges for both of those functions to produce [unknown value](https://opentofu.org/docs/v1.10/language/expressions/references/#values-not-yet-known) results during the plan step, with the real result being decided only during the apply step. For `timestamp` in particular, this means that the recorded time will be the instant when OpenTofu began applying the change, rather than when OpenTofu _planned_ the change. For more details on the behavior of these functions, refer to their own documentation pages. * [Available Functions](https://opentofu.org/docs/v1.10/language/expressions/function-calls/#available-functions) * [Expanding Function Arguments](https://opentofu.org/docs/v1.10/language/expressions/function-calls/#expanding-function-arguments) * [Using Sensitive Data as Function Arguments](https://opentofu.org/docs/v1.10/language/expressions/function-calls/#using-sensitive-data-as-function-arguments) * [When OpenTofu Calls Functions](https://opentofu.org/docs/v1.10/language/expressions/function-calls/#when-opentofu-calls-functions) --- # Version Constraints | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Version Constraints =================== Anywhere that OpenTofu lets you specify a range of acceptable versions for something, it expects a specially formatted string known as a version constraint. Version constraints are used when configuring: * [Modules](https://opentofu.org/docs/v1.10/language/modules/) * [Provider requirements](https://opentofu.org/docs/v1.10/language/providers/requirements/) * [The `required_version` setting](https://opentofu.org/docs/v1.10/language/settings/#specifying-a-required-tofu-version) in the `terraform` block. Version Constraint Syntax[​](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#version-constraint-syntax "Direct link to Version Constraint Syntax") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu's syntax for version constraints is very similar to the syntax used by other dependency management systems like Bundler and NPM. Code Block version = ">= 1.2.0, < 2.0.0" A version constraint is a [string literal](https://opentofu.org/docs/v1.10/language/expressions/strings/) containing one or more conditions, which are separated by commas. Each condition consists of an operator and a version number. Version numbers should be a series of numbers separated by periods (like `1.2.0`), optionally with a suffix to indicate a beta release. The following operators are valid: * `=` (or no operator): Allows only one exact version number. Cannot be combined with other conditions. * `!=`: Excludes an exact version number. * `>`, `>=`, `<`, `<=`: Comparisons against a specified version, allowing versions for which the comparison is true. "Greater-than" requests newer versions, and "less-than" requests older versions. * `~>`: Allows only the _rightmost_ version component to increment. For example, to allow new patch releases within a specific minor release, use the full version number: `~> 1.0.4` will allow installation of `1.0.5` and `1.0.10` but not `1.1.0`. This is usually called the pessimistic constraint operator. Version Constraint Behavior[​](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#version-constraint-behavior "Direct link to Version Constraint Behavior") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A version number that meets every applicable constraint is considered acceptable. OpenTofu consults version constraints to determine whether it has acceptable versions of itself, any required provider plugins, and any required modules. For plugins and modules, it will use the newest installed version that meets the applicable constraints. If OpenTofu doesn't have an acceptable version of a required plugin or module, it will attempt to download the newest version that meets the applicable constraints. If OpenTofu isn't able to obtain acceptable versions of external dependencies, or if it doesn't have an acceptable version of itself, it won't proceed with any plans, applies, or state manipulation actions. Both the root module and any child module can constrain the acceptable versions of OpenTofu and any providers they use. OpenTofu considers these constraints equal, and will only proceed if all of them can be met. A prerelease version is a version number that contains a suffix introduced by a dash, like `1.2.0-beta`. A prerelease version can be selected only by an _exact_ version constraint (the `=` operator or no operator). Prerelease versions do not match inexact operators such as `>=`, `~>`, etc. Best Practices[​](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#best-practices "Direct link to Best Practices") -------------------------------------------------------------------------------------------------------------------------------------------- ### Module Versions[​](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#module-versions "Direct link to Module Versions") * When depending on third-party modules, require specific versions to ensure that updates only happen when convenient to you. * For modules maintained within your organization, specifying version ranges may be appropriate if semantic versioning is used consistently or if there is a well-defined release process that avoids unwanted updates. ### OpenTofu Core and Provider Versions[​](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#opentofu-core-and-provider-versions "Direct link to OpenTofu Core and Provider Versions") * Reusable modules should constrain only their minimum allowed versions of OpenTofu and providers, such as `>= 0.12.0`. This helps avoid known incompatibilities, while allowing the user of the module flexibility to upgrade to newer versions of OpenTofu without altering the module. * Root modules should use a `~>` constraint to set both a lower and upper bound on versions for each provider they depend on. ### Supporting both OpenTofu and Terraform Versions[​](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#supporting-both-opentofu-and-terraform-versions "Direct link to Supporting both OpenTofu and Terraform Versions") * When configuration needs to be supported by both OpenTofu and Terraform, for example in modules which need to be consumed by both engines, use a `providers.tofu` file to specify the OpenTofu version constraint, overriding the constraint defined in `providers.tf`. [Read more about extension precedence](https://opentofu.org/docs/v1.10/language/files/#extension-precedence) . * [Version Constraint Syntax](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#version-constraint-syntax) * [Version Constraint Behavior](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#version-constraint-behavior) * [Best Practices](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#best-practices) * [Module Versions](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#module-versions) * [OpenTofu Core and Provider Versions](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#opentofu-core-and-provider-versions) * [Supporting both OpenTofu and Terraform Versions](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/#supporting-both-opentofu-and-terraform-versions) --- # References to Named Values | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/expressions/references/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page References to Named Values ========================== OpenTofu makes several kinds of named values available. Each of these names is an expression that references the associated value. You can use them as standalone expressions, or combine them with other expressions to compute new values. Types of Named Values[​](https://opentofu.org/docs/v1.10/language/expressions/references/#types-of-named-values "Direct link to Types of Named Values") -------------------------------------------------------------------------------------------------------------------------------------------------------- The main kinds of named values available in OpenTofu are: * Resources * Input variables * Local values * Child module outputs * Data sources * Filesystem and workspace info * Block-local values The sections below explain each kind of named value in detail. Although many of these names use dot-separated paths that resemble [attribute notation](https://opentofu.org/docs/v1.10/language/expressions/types/#indices-and-attributes) for elements of object values, they are not implemented as real objects. This means you must use them exactly as written: you cannot use square-bracket notation to replace the dot-separated paths, and you cannot iterate over the "parent object" of a named entity; for example, you cannot use `aws_instance` in a `for` expression to iterate over every AWS instance resource. ### Resources[​](https://opentofu.org/docs/v1.10/language/expressions/references/#resources "Direct link to Resources") `.` represents a [managed resource](https://opentofu.org/docs/v1.10/language/resources/) of the given type and name. The value of a resource reference can vary, depending on whether the resource uses `count` or `for_each`: * If the resource doesn't use `count` or `for_each`, the reference's value is an object. The resource's attributes are elements of the object, and you can access them using [dot or square bracket notation](https://opentofu.org/docs/v1.10/language/expressions/types/#indices-and-attributes) . * If the resource has the `count` argument set, the reference's value is a _list_ of objects representing its instances. * If the resource has the `for_each` argument set, the reference's value is a _map_ of objects representing its instances. Any named value that does not match another pattern listed below will be interpreted by OpenTofu as a reference to a managed resource. For more information about how to use resource references, see [references to resource attributes](https://opentofu.org/docs/v1.10/language/expressions/references/#references-to-resource-attributes) below. ### Input Variables[​](https://opentofu.org/docs/v1.10/language/expressions/references/#input-variables "Direct link to Input Variables") `var.` is the value of the [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) of the given name. If the variable has a type constraint (`type` argument) as part of its declaration, OpenTofu will automatically convert the caller's given value to conform to the type constraint. For that reason, you can safely assume that a reference using `var.` will always produce a value that conforms to the type constraint, even if the caller provided a value of a different type that was automatically converted. In particular, note that if you define a variable as being of an object type with particular attributes then only _those specific attributes_ will be available in expressions elsewhere in the module, even if the caller actually passed in a value with additional attributes. You must define in the type constraint all of the attributes you intend to use elsewhere in your module. ### Local Values[​](https://opentofu.org/docs/v1.10/language/expressions/references/#local-values "Direct link to Local Values") `local.` is the value of the [local value](https://opentofu.org/docs/v1.10/language/values/locals/) of the given name. Local values can refer to other local values, even within the same `locals` block, as long as you don't introduce circular dependencies. ### Child Module Outputs[​](https://opentofu.org/docs/v1.10/language/expressions/references/#child-module-outputs "Direct link to Child Module Outputs") `module.` is an value representing the results of [a `module` block](https://opentofu.org/docs/v1.10/language/modules/syntax/) . If the corresponding `module` block does not have either `count` nor `for_each` set then the value will be an object with one attribute for each output value defined in the child module. To access one of the module's [output values](https://opentofu.org/docs/v1.10/language/values/outputs/) , use `module..`. If the corresponding `module` uses `for_each` then the value will be a map of objects whose keys correspond with the keys in the `for_each` expression, and whose values are each objects with one attribute for each output value defined in the child module, each representing one module instance. If the corresponding module uses `count` then the result is similar to for `for_each` except that the value is a _list_ with the requested number of elements, each one representing one module instance. ### Data Sources[​](https://opentofu.org/docs/v1.10/language/expressions/references/#data-sources "Direct link to Data Sources") `data..` is an object representing a [data resource](https://opentofu.org/docs/v1.10/language/data-sources/) of the given data source type and name. If the resource has the `count` argument set, the value is a list of objects representing its instances. If the resource has the `for_each` argument set, the value is a map of objects representing its instances. For more information, see [References to Resource Attributes](https://opentofu.org/docs/v1.10/language/expressions/references/#references-to-resource-attributes) , which also applies to data resources aside from the addition of the `data.` prefix to mark the reference as for a data resource. ### Filesystem and Workspace Info[​](https://opentofu.org/docs/v1.10/language/expressions/references/#filesystem-and-workspace-info "Direct link to Filesystem and Workspace Info") The following values are available: * `path.module` is the filesystem path of the module where the expression is placed. We do not recommend using `path.module` in write operations because it can produce different behavior depending on whether you use remote or local module sources. Multiple invocations of local modules use the same source directory, overwriting the data in `path.module` during each call. This can lead to race conditions and unexpected results. * `path.root` is the filesystem path of the root module of the configuration. * `path.cwd` is the filesystem path of the original working directory from where you ran OpenTofu before applying any `-chdir` argument. This path is an absolute path that includes details about the filesystem structure. It is also useful in some advanced cases where OpenTofu is run from a directory other than the root module directory. We recommend using `path.root` or `path.module` over `path.cwd` where possible. * `terraform.workspace` is the name of the currently selected [workspace](https://opentofu.org/docs/v1.10/language/state/workspaces/) . Use the values in this section carefully, because they include information about the context in which a configuration is being applied and so may inadvertently hurt the portability or composability of a module. For example, if you use `path.cwd` directly to populate a path into a resource argument then later applying the same configuration from a different directory or on a different computer with a different directory structure will cause the provider to consider the change of path to be a change to be applied, even if the path still refers to the same file. Similarly, if you use any of these values as a form of namespacing in a shared module, such as using `terraform.workspace` as a prefix for globally-unique object names, it may not be possible to call your module more than once in the same configuration. Aside from `path.module`, we recommend using the values in this section only in the root module of your configuration. If you are writing a shared module which needs a prefix to help create unique names, define an input variable for your module and allow the calling module to define the prefix. The calling module can then use `terraform.workspace` to define it if appropriate, or some other value if not: Code Block module "example" { # ... name_prefix = "app-${terraform.workspace}"} ### Block-Local Values[​](https://opentofu.org/docs/v1.10/language/expressions/references/#block-local-values "Direct link to Block-Local Values") Within the bodies of certain blocks, or in some other specific contexts, there are other named values available beyond the global values listed above. These local names are described in the documentation for the specific contexts where they appear. Some of most common local names are: * `count.index`, in resources that use [the `count` meta-argument](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) . * `each.key` / `each.value`, in resources that use [the `for_each` meta-argument](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) . * `self`, in [provisioner](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/) and [connection](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/) blocks. Note Local names are often referred to as _variables_ or _temporary variables_ in their documentation. These are not [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) ; they are just arbitrary names that temporarily represent a value. The names in this section relate to top-level configuration blocks only. If you use [`dynamic` blocks](https://opentofu.org/docs/v1.10/language/expressions/dynamic-blocks/) to dynamically generate resource-type-specific _nested_ blocks within `resource` and `data` blocks then you'll refer to the key and value of each element differently. See the `dynamic` blocks documentation for details. Named Values and Dependencies[​](https://opentofu.org/docs/v1.10/language/expressions/references/#named-values-and-dependencies "Direct link to Named Values and Dependencies") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Constructs like resources and module calls often use references to named values in their block bodies, and OpenTofu analyzes these expressions to automatically infer dependencies between objects. For example, an expression in a resource argument that refers to another managed resource creates an implicit dependency between the two resources. References to Resource Attributes[​](https://opentofu.org/docs/v1.10/language/expressions/references/#references-to-resource-attributes "Direct link to References to Resource Attributes") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The most common reference type is a reference to an attribute of a resource which has been declared either with a `resource` or `data` block. Because the contents of such blocks can be quite complicated themselves, expressions referring to these contents can also be complicated. Consider the following example resource block: Code Block resource "aws_instance" "example" { ami = "ami-abc123" instance_type = "t2.micro" ebs_block_device { device_name = "sda2" volume_size = 16 } ebs_block_device { device_name = "sda3" volume_size = 20 }} The documentation for [`aws_instance`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) lists all of the arguments and nested blocks supported for this resource type, and also lists a number of attributes that are _exported_ by this resource type. All of these different resource type schema constructs are available for use in references, as follows: * The `ami` argument set in the configuration can be used elsewhere with the reference expression `aws_instance.example.ami`. * The `id` attribute exported by this resource type can be read using the same syntax, giving `aws_instance.example.id`. * The arguments of the `ebs_block_device` nested blocks can be accessed using a [splat expression](https://opentofu.org/docs/v1.10/language/expressions/splat/) . For example, to obtain a list of all of the `device_name` values, use `aws_instance.example.ebs_block_device[*].device_name`. * The nested blocks in this particular resource type do not have any exported attributes, but if `ebs_block_device` were to have a documented `id` attribute then a list of them could be accessed similarly as `aws_instance.example.ebs_block_device[*].id`. * Sometimes nested blocks are defined as taking a logical key to identify each block, which serves a similar purpose as the resource's own name by providing a convenient way to refer to that single block in expressions. If `aws_instance` had a hypothetical nested block type `device` that accepted such a key, it would look like this in configuration: Code Block device "foo" { size = 2 } device "bar" { size = 4 } Arguments inside blocks with _keys_ can be accessed using index syntax, such as `aws_instance.example.device["foo"].size`. To obtain a map of values of a particular argument for _labelled_ nested block types, use a [`for` expression](https://opentofu.org/docs/v1.10/language/expressions/for/) : `{for k, device in aws_instance.example.device : k => device.size}`. When a resource has the [`count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) argument set, the resource itself becomes a _list_ of instance objects rather than a single object. In that case, access the attributes of the instances using either [splat expressions](https://opentofu.org/docs/v1.10/language/expressions/splat/) or index syntax: * `aws_instance.example[*].id` returns a list of all of the ids of each of the instances. * `aws_instance.example[0].id` returns just the id of the first instance. When a resource has the [`for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) argument set, the resource itself becomes a _map_ of instance objects rather than a single object, and attributes of instances must be specified by key, or can be accessed using a [`for` expression](https://opentofu.org/docs/v1.10/language/expressions/for/) . * `aws_instance.example["a"].id` returns the id of the "a"-keyed resource. * `[for value in aws_instance.example: value.id]` returns a list of all of the ids of each of the instances. Note that unlike `count`, splat expressions are _not_ directly applicable to resources managed with `for_each`, as splat expressions must act on a list value. However, you can use the `values()` function to extract the instances as a list and use that list value in a splat expression: * `values(aws_instance.example)[*].id` ### Sensitive Resource Attributes[​](https://opentofu.org/docs/v1.10/language/expressions/references/#sensitive-resource-attributes "Direct link to Sensitive Resource Attributes") When defining the schema for a resource type, a provider developer can mark certain attributes as _sensitive_, in which case OpenTofu will show a placeholder marker `(sensitive value)` instead of the actual value when rendering a plan involving that attribute. A provider attribute marked as sensitive behaves similarly to an [an input variable declared as sensitive](https://opentofu.org/docs/v1.10/language/values/variables/#suppressing-values-in-cli-output) , where OpenTofu will hide the value in the plan and apply messages and will also hide any other values you derive from it as sensitive. However, there are some limitations to that behavior as described in [Cases where OpenTofu may disclose a sensitive variable](https://opentofu.org/docs/v1.10/language/values/variables/#cases-where-tofu-may-disclose-a-sensitive-variable) . If you use a sensitive value from a resource attribute as part of an [output value](https://opentofu.org/docs/v1.10/language/values/outputs/) then OpenTofu will require you to also mark the output value itself as sensitive, to confirm that you intended to export it. OpenTofu will still record sensitive values in the [state](https://opentofu.org/docs/v1.10/language/state/) , and so anyone who can access the state data will have access to the sensitive values in cleartext. For more information, see [_Sensitive Data in State_](https://opentofu.org/docs/v1.10/language/state/sensitive-data/) . ### Values Not Yet Known[​](https://opentofu.org/docs/v1.10/language/expressions/references/#values-not-yet-known "Direct link to Values Not Yet Known") When OpenTofu is planning a set of changes that will apply your configuration, some resource attribute values cannot be populated immediately because their values are decided dynamically by the remote system. For example, if a particular remote object type is assigned a generated unique id on creation, OpenTofu cannot predict the value of this id until the object has been created. OpenTofu uses special unknown value placeholders for information that it cannot predict during the plan phase. The OpenTofu language automatically handles unknown values in expressions. For example, adding a known value to an unknown value automatically produces an unknown value as a result. However, there are some situations where unknown values _do_ have a significant effect: * The `count` meta-argument for resources cannot be unknown, since it must be evaluated during the plan phase to determine how many instances are to be created. * If unknown values are used in the configuration of a data resource, that data resource cannot be read during the plan phase and so it will be deferred until the apply phase. In this case, the results of the data resource will _also_ be unknown values. * If an unknown value is assigned to an argument inside a `module` block, any references to the corresponding input variable within the child module will use that unknown value. * If an unknown value is used in the `value` argument of an output value, any references to that output value in the parent module will use that unknown value. * OpenTofu will attempt to validate that unknown values are of suitable types where possible, but incorrect use of such values may not be detected until the apply phase, causing the apply to fail. Unknown values appear in the `tofu plan` output as `(known after apply)`. * [Types of Named Values](https://opentofu.org/docs/v1.10/language/expressions/references/#types-of-named-values) * [Resources](https://opentofu.org/docs/v1.10/language/expressions/references/#resources) * [Input Variables](https://opentofu.org/docs/v1.10/language/expressions/references/#input-variables) * [Local Values](https://opentofu.org/docs/v1.10/language/expressions/references/#local-values) * [Child Module Outputs](https://opentofu.org/docs/v1.10/language/expressions/references/#child-module-outputs) * [Data Sources](https://opentofu.org/docs/v1.10/language/expressions/references/#data-sources) * [Filesystem and Workspace Info](https://opentofu.org/docs/v1.10/language/expressions/references/#filesystem-and-workspace-info) * [Block-Local Values](https://opentofu.org/docs/v1.10/language/expressions/references/#block-local-values) * [Named Values and Dependencies](https://opentofu.org/docs/v1.10/language/expressions/references/#named-values-and-dependencies) * [References to Resource Attributes](https://opentofu.org/docs/v1.10/language/expressions/references/#references-to-resource-attributes) * [Sensitive Resource Attributes](https://opentofu.org/docs/v1.10/language/expressions/references/#sensitive-resource-attributes) * [Values Not Yet Known](https://opentofu.org/docs/v1.10/language/expressions/references/#values-not-yet-known) --- # Type Constraints | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Type Constraints ================ OpenTofu module authors and provider developers can use detailed type constraints to validate user-provided values for their input variables and resource arguments. This requires some additional knowledge about OpenTofu's type system, but allows you to build a more resilient user interface for your modules and resources. Type Keywords and Constructors[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#type-keywords-and-constructors "Direct link to Type Keywords and Constructors") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Type constraints are expressed using a mixture of _type keywords_ and function-like constructs called _type constructors._ * Type keywords are unquoted symbols that represent a static type. * Type constructors are unquoted symbols followed by a pair of parentheses, which contain an argument that specifies more information about the type. Without its argument, a type constructor does not fully represent a type; instead, it represents a _kind_ of similar types. Type constraints look like other kinds of OpenTofu [expressions](https://opentofu.org/docs/v1.10/) , but are a special syntax. Within the OpenTofu language, they are only valid in the `type` argument of an [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) . Primitive Types[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#primitive-types "Direct link to Primitive Types") -------------------------------------------------------------------------------------------------------------------------------------------- A _primitive_ type is a simple type that isn't made from any other types. All primitive types in OpenTofu are represented by a type keyword. The available primitive types are: * `string`: a sequence of Unicode characters representing some text, such as `"hello"`. * `number`: a numeric value. The `number` type can represent both whole numbers like `15` and fractional values such as `6.283185`. * `bool`: either `true` or `false`. `bool` values can be used in conditional logic. ### Conversion of Primitive Types[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#conversion-of-primitive-types "Direct link to Conversion of Primitive Types") The OpenTofu language will automatically convert `number` and `bool` values to `string` values when needed, and vice-versa as long as the string contains a valid representation of a number or boolean value. * `true` converts to `"true"`, and vice-versa * `false` converts to `"false"`, and vice-versa * `15` converts to `"15"`, and vice-versa Complex Types[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#complex-types "Direct link to Complex Types") -------------------------------------------------------------------------------------------------------------------------------------- A _complex_ type is a type that groups multiple values into a single value. Complex types are represented by type constructors, but several of them also have shorthand keyword versions. There are two categories of complex types: collection types (for grouping similar values), and structural types (for grouping potentially dissimilar values). ### Collection Types[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#collection-types "Direct link to Collection Types") A _collection_ type allows multiple values of _one_ other type to be grouped together as a single value. The type of value _within_ a collection is called its _element type._ All collection types must have an element type, which is provided as the argument to their constructor. For example, the type `list(string)` means "list of strings", which is a different type than `list(number)`, a list of numbers. All elements of a collection must always be of the same type. The three kinds of collection type in the OpenTofu language are: * `list(...)`: a sequence of values identified by consecutive whole numbers starting with zero. The keyword `list` is a shorthand for `list(any)`, which accepts any element type as long as every element is the same type. This is for compatibility with older configurations; for new code, we recommend using the full form. * `map(...)`: a collection of values where each is identified by a string label. The keyword `map` is a shorthand for `map(any)`, which accepts any element type as long as every element is the same type. This is for compatibility with older configurations; for new code, we recommend using the full form. Maps can be made with braces () and colons (:) or equals signs (=): { "foo": "bar", "bar": "baz" } OR { foo = "bar", bar = "baz" }. Quotes may be omitted on keys, unless the key starts with a number, in which case quotes are required. Commas are required between key/value pairs for single line maps. A newline between key/value pairs is sufficient in multi-line maps. Note Although colons are valid delimiters between keys and values, `tofu fmt` ignores them. In contrast, `tofu fmt` attempts to vertically align equals signs. * `set(...)`: a collection of unique values that do not have any secondary identifiers or ordering. ### Structural Types[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#structural-types "Direct link to Structural Types") A _structural_ type allows multiple values of _several distinct types_ to be grouped together as a single value. Structural types require a _schema_ as an argument, to specify which types are allowed for which elements. The two kinds of structural type in the OpenTofu language are: * `object(...)`: a collection of named attributes that each have their own type. The schema for object types is `{ = , = , ... }` β€”Β a pair of curly braces containing a comma-separated series of ` = ` pairs. Values that match the object type must contain _all_ of the specified keys, and the value for each key must match its specified type. (Values with _additional_ keys can still match an object type, but the extra attributes are discarded during type conversion.) * `tuple(...)`: a sequence of elements identified by consecutive whole numbers starting with zero, where each element has its own type. The schema for tuple types is `[, , ...]` β€”Β a pair of square brackets containing a comma-separated series of types. Values that match the tuple type must have _exactly_ the same number of elements (no more and no fewer), and the value in each position must match the specified type for that position. For example: an object type of `object({ name=string, age=number })` would match a value like the following: Code Block { name = "John" age = 52} Also, an object type of `object({ id=string, cidr_block=string })` would match the object produced by a reference to an `aws_vpc` resource, like `aws_vpc.example_vpc`; although the resource has additional attributes, they would be discarded during type conversion. Finally, a tuple type of `tuple([string, number, bool])` would match a value like the following: Code Block ["a", 15, true] ### Complex Type Literals[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#complex-type-literals "Direct link to Complex Type Literals") The OpenTofu language has literal expressions for creating tuple and object values, which are described in [Expressions: Literal Expressions](https://opentofu.org/docs/v1.10/language/expressions/types/#literal-expressions) as "list/tuple" literals and "map/object" literals, respectively. OpenTofu does _not_ provide any way to directly represent lists, maps, or sets. However, due to the automatic conversion of complex types (described below), the difference between similar complex types is almost never relevant to a normal user, and most of the OpenTofu documentation conflates lists with tuples and maps with objects. The distinctions are only useful when restricting input values for a module or resource. ### Conversion of Complex Types[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#conversion-of-complex-types "Direct link to Conversion of Complex Types") Similar kinds of complex types (list/tuple/set and map/object) can usually be used interchangeably within the OpenTofu language, and most of OpenTofu's documentation glosses over the differences between the kinds of complex type. This is due to two conversion behaviors: * Whenever possible, OpenTofu converts values between similar kinds of complex types if the provided value is not the exact type requested. "Similar kinds" is defined as follows: * Objects and maps are similar. * A map (or a larger object) can be converted to an object if it has _at least_ the keys required by the object schema. Any additional attributes are discarded during conversion, which means map -> object -> map conversions can be lossy. * Tuples and lists are similar. * A list can only be converted to a tuple if it has _exactly_ the required number of elements. * Sets are _almost_ similar to both tuples and lists: * When a list or tuple is converted to a set, duplicate values are discarded and the ordering of elements is lost. * When a `set` is converted to a list or tuple, the elements will be in an arbitrary order. If the set's elements were strings, they will be in lexicographical order; sets of other element types do not guarantee any particular order of elements. * Whenever possible, OpenTofu converts _element values_ within a complex type, either by converting complex-typed elements recursively or as described above in [Conversion of Primitive Types](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#conversion-of-primitive-types) . For example: if a module argument requires a value of type `list(string)` and a user provides the tuple `["a", 15, true]`, OpenTofu will internally transform the value to `["a", "15", "true"]` by converting the elements to the required `string` element type. Later, if the module uses those elements to set different resource arguments that require a string, a number, and a bool (respectively), OpenTofu will automatically convert the second and third strings back to the required types at that time, since they contain valid representations of a number and a bool. On the other hand, automatic conversion will fail if the provided value (including any of its element values) is incompatible with the required type. If an argument requires a type of `map(string)` and a user provides the object `{name = ["Kristy", "Claudia", "Mary Anne", "Stacey"], age = 12}`, OpenTofu will raise a type mismatch error, since a tuple cannot be converted to a string. Dynamic Types: The "any" Constraint[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#dynamic-types-the-any-constraint "Direct link to Dynamic Types: The "any" Constraint") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Warning `any` is very rarely the correct type constraint to use. **Do not use `any` just to avoid specifying a type constraint**. Always write an exact type constraint unless you are truly handling dynamic data. The keyword `any` is a special construct that serves as a placeholder for a type yet to be decided. `any` is not _itself_ a type: when interpreting a value against a type constraint containing `any`, OpenTofu will attempt to find a single actual type that could replace the `any` keyword to produce a valid result. The only situation where it's appropriate to use `any` is if you will pass the given value directly to some other system without directly accessing its contents. For example, it's okay to use a variable of type `any` if you use it only with `jsonencode` to pass the full value directly to a resource, as shown in the following example: Code Block variable "settings" { type = any}resource "aws_s3_object" "example" { # ... # This is a reasonable use of "any" because this module # just writes any given data to S3 as JSON, without # inspecting it further or applying any constraints # to its type or value. content = jsonencode(var.settings)} If any part of your module accesses elements or attributes of the value, or expects it to be a string or number, or any other non-opaque treatment, it is _incorrect_ to use `any`. Write the exact type that your module is expecting instead. ### `any` with Collection Types[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#any-with-collection-types "Direct link to any-with-collection-types") All of the elements of a collection must have the same type, so if you use `any` as the placeholder for the element type of a collection then OpenTofu will attempt to find a single exact element type to use for the resulting collection. For example, given the type constraint `list(any)`, OpenTofu will examine the given value and try to choose a replacement for the `any` that would make the result valid. If the given value were `["a", "b", "c"]` -- whose physical type is `tuple([string, string, string])` -- OpenTofu analyzes this as follows: * Tuple types and list types are _similar_ per the previous section, so the tuple-to-list conversion rule applies. * All of the elements in the tuple are strings, so the type constraint `string` would be valid for all of the list elements. * Therefore in this case the `any` argument is replaced with `string`, and the final concrete value type is `list(string)`. If the elements of the given tuple are not all of the same type then OpenTofu will attempt to find a single type that they can all convert to. OpenTofu will consider various conversion rules as described in earlier sections. * If the given value were instead `["a", 1, "b"]` then OpenTofu would still select `list(string)`, because of the primitive type conversion rules, and the resulting value would be `["a", "1", "b"]` due to the string conversion implied by that type constraint. * If the given value were instead `["a", [], "b"]` then the value cannot conform to the type constraint: there is no single type that both a string and an empty tuple can convert to. OpenTofu would reject this value, complaining that all elements must have the same type. Although the above examples use `list(any)`, a similar principle applies to `map(any)` and `set(any)`. Optional Object Type Attributes[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#optional-object-type-attributes "Direct link to Optional Object Type Attributes") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu typically returns an error when it does not receive a value for specified object attributes. When you mark an attribute as optional, OpenTofu instead inserts a default value for the missing attribute. This allows the receiving module to describe an appropriate fallback behavior. To mark attributes as optional, use the `optional` modifier in the object type constraint. The following example creates optional attribute `b` and optional attribute with a default value `c`. Code Block variable "with_optional_attribute" { type = object({ a = string # a required attribute b = optional(string) # an optional attribute c = optional(number, 127) # an optional attribute with default value })} The `optional` modifier takes one or two arguments. * **Type:** (Required) The first argument specifies the type of the attribute. * **Default:** (Optional) The second argument defines the default value that OpenTofu should use if the attribute is not present. This must be compatible with the attribute type. If not specified, OpenTofu uses a `null` value of the appropriate type as the default. An optional attribute with a non-`null` default value is guaranteed to never have the value `null` within the receiving module. OpenTofu will substitute the default value both when a caller omits the attribute altogether and when a caller explicitly sets it to `null`, thereby avoiding the need for additional checks to handle a possible null value. OpenTofu applies object attribute defaults top-down in nested variable types. This means that OpenTofu applies the default value you specify in the `optional` modifier first and then later applies any nested default values to that attribute. ### Example: Nested Structures with Optional Attributes and Defaults[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#example-nested-structures-with-optional-attributes-and-defaults "Direct link to Example: Nested Structures with Optional Attributes and Defaults") The following example defines a variable for storage buckets that host a website. This variable type uses several optional attributes, including `website`, which is itself an optional `object` type that has optional attributes and defaults. Code Block variable "buckets" { type = list(object({ name = string enabled = optional(bool, true) website = optional(object({ index_document = optional(string, "index.html") error_document = optional(string, "error.html") routing_rules = optional(string) }), {}) }))} The following example `terraform.tfvars` file specifies three bucket configurations for `var.buckets`. * `production` sets the routing rules to add a redirect * `archived` uses default configuration, but is disabled * `docs` overrides the index and error documents to use text files The `production` bucket does not specify the index and error documents, and the `archived` bucket omits the website configuration entirely. OpenTofu will use the default values specified in the `bucket` type constraint. Code Block buckets = [ { name = "production" website = { routing_rules = <<-EOT [ { "Condition" = { "KeyPrefixEquals": "img/" }, "Redirect" = { "ReplaceKeyPrefixWith": "images/" } } ] EOT } }, { name = "archived" enabled = false }, { name = "docs" website = { index_document = "index.txt" error_document = "error.txt" } },] This configuration produces the following variable values. * For the `production` and `docs` buckets, OpenTofu sets `enabled` to `true`. OpenTofu also supplies default values for `website`, and then the values specified in `docs` override those defaults. * For the `archived` and `docs` buckets, OpenTofu sets `routing_rules` to a `null` value. When OpenTofu does not receive optional attributes and there are no specified defaults, OpenTofu populates those attributes with a `null` value. * For the `archived` bucket, OpenTofu populates the `website` attribute with the default values specified in the `buckets` type constraint. Code Block tolist([ { "enabled" = true "name" = "production" "website" = { "error_document" = "error.html" "index_document" = "index.html" "routing_rules" = <<-EOT [ { "Condition" = { "KeyPrefixEquals": "img/" }, "Redirect" = { "ReplaceKeyPrefixWith": "images/" } } ] EOT } }, { "enabled" = false "name" = "archived" "website" = { "error_document" = "error.html" "index_document" = "index.html" "routing_rules" = tostring(null) } }, { "enabled" = true "name" = "docs" "website" = { "error_document" = "error.txt" "index_document" = "index.txt" "routing_rules" = tostring(null) } },]) ### Example: Conditionally setting an optional attribute[​](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#example-conditionally-setting-an-optional-attribute "Direct link to Example: Conditionally setting an optional attribute") Sometimes the decision about whether or not to set a value for an optional argument needs to be made dynamically based on some other data. In that case, the calling `module` block can use a conditional expression with `null` as one of its result arms to represent dynamically leaving the argument unset. With the `variable "buckets"` declaration shown in the previous section, the following example conditionally overrides the `index_document` and `error_document` settings in the `website` object based on a new variable `var.legacy_filenames`: Code Block variable "legacy_filenames" { type = bool default = false nullable = false}module "buckets" { source = "./modules/buckets" buckets = [ { name = "maybe_legacy" website = { error_document = var.legacy_filenames ? "ERROR.HTM" : null index_document = var.legacy_filenames ? "INDEX.HTM" : null } }, ]} When `var.legacy_filenames` is set to `true`, the call will override the document filenames. When it is `false`, the call will leave the two filenames unspecified, thereby allowing the module to use its specified default values. * [Type Keywords and Constructors](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#type-keywords-and-constructors) * [Primitive Types](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#primitive-types) * [Conversion of Primitive Types](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#conversion-of-primitive-types) * [Complex Types](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#complex-types) * [Collection Types](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#collection-types) * [Structural Types](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#structural-types) * [Complex Type Literals](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#complex-type-literals) * [Conversion of Complex Types](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#conversion-of-complex-types) * [Dynamic Types: The "any" Constraint](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#dynamic-types-the-any-constraint) * [`any` with Collection Types](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#any-with-collection-types) * [Optional Object Type Attributes](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#optional-object-type-attributes) * [Example: Nested Structures with Optional Attributes and Defaults](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#example-nested-structures-with-optional-attributes-and-defaults) * [Example: Conditionally setting an optional attribute](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#example-conditionally-setting-an-optional-attribute) --- # Custom Conditions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Custom Conditions ================= You can create conditions that produce custom error messages for several types of objects in a configuration. For example, you can add a condition to an input variable that checks whether incoming image IDs are formatted properly. Custom conditions can capture assumptions, helping future maintainers understand the configuration design and intent. They also return useful information about errors earlier and in context, helping consumers more easily diagnose issues in their configurations. This page explains the following: * Creating checks with [assertions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#checks-with-assertions) to verify your infrastructure as a whole * Creating [validation conditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#input-variable-validation) for input variables * Creating [preconditions and postconditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#preconditions-and-postconditions) for resources, data sources, and outputs * Writing effective [condition expressions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#condition-expressions) and [error messages](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#error-messages) * When OpenTofu [evaluates custom conditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#conditions-checked-only-during-apply) during the plan and apply cycle Selecting a Custom Condition for your use case[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#selecting-a-custom-condition-for-your-use-case "Direct link to Selecting a Custom Condition for your use case") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ OpenTofu's different custom conditions are best suited to various situations. Use the following broad guidelines to select the best custom condition for your use case: 1. [Check blocks with assertions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#checks-with-assertions) validate your infrastructure as a whole. Additionally, check blocks do not prevent or block the overall execution of OpenTofu operations. 2. [Validation conditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#input-variable-validation) or [output postconditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#preconditions-and-postconditions) can ensure your configuration's inputs and outputs meet specific requirements. 3. Resource [preconditions and postconditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#preconditions-and-postconditions) can validate that OpenTofu produces your configuration with predictable results. For more information on when to use certain custom conditions, see [Choosing Between Preconditions and Postconditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#choosing-between-preconditions-and-postconditions) and [Choosing Checks or Other Custom Conditions](https://opentofu.org/docs/v1.10/language/checks/#choosing-checks-or-other-custom-conditions) . Input Variable Validation[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#input-variable-validation "Direct link to Input Variable Validation") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Add one or more `validation` blocks within the `variable` block to specify custom conditions. Each validation requires a [`condition` argument](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#condition-expressions) , an expression that must use the value of the variable to return `true` if the value is valid, or `false` if it is invalid. The expression can refer to variables, locals, resources, etc. If a variable is unknown during validate/plan, the validation is deferred until the value is known during apply. If the condition evaluates to `false`, OpenTofu produces an [error message](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#error-messages) that includes the result of the `error_message` expression. If you declare multiple validations, OpenTofu returns error messages for all failed conditions. The following example checks whether the AMI ID has valid syntax. Code Block variable "image_id" { type = string description = "The id of the machine image (AMI) to use for the server." validation { condition = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-" error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"." }} If the failure of an expression determines the validation decision, use the [`can` function](https://opentofu.org/docs/v1.10/language/functions/can/) as demonstrated in the following example. Code Block variable "image_id" { type = string description = "The id of the machine image (AMI) to use for the server." validation { # regex(...) fails if it cannot find a match condition = can(regex("^ami-", var.image_id)) error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"." }} Preconditions and Postconditions[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#preconditions-and-postconditions "Direct link to Preconditions and Postconditions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Use `precondition` and `postcondition` blocks to create custom rules for resources, data sources, and outputs. OpenTofu checks a precondition _before_ evaluating the object it is associated with and checks a postcondition _after_ evaluating the object. OpenTofu evaluates custom conditions as early as possible, but must defer conditions that depend on unknown values until the apply phase. Refer to [Conditions Checked Only During Apply](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#conditions-checked-only-during-apply) for more details. ### Usage[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#usage "Direct link to Usage") Each precondition and postcondition requires a [`condition` argument](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#condition-expressions) . This is an expression that must return `true` if the conditition is fulfilled or `false` if it is invalid. The expression can refer to any other objects in the same module, as long as the references do not create cyclic dependencies. Resource postconditions can also use the [`self` object](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#self-object) to refer to attributes of each instance of the resource where they are configured. If the condition evaluates to `false`, OpenTofu will produce an [error message](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#error-messages) that includes the result of the `error_message` expression. If you declare multiple preconditions or postconditions, OpenTofu returns error messages for all failed conditions. The following example uses a postcondition to detect if the caller accidentally provided an AMI intended for the wrong system component. Code Block data "aws_ami" "example" { id = var.aws_ami_id lifecycle { # The AMI ID must refer to an existing AMI that has the tag "nomad-server". postcondition { condition = self.tags["Component"] == "nomad-server" error_message = "tags[\"Component\"] must be \"nomad-server\"." } }} #### Resources and Data Sources[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#resources-and-data-sources "Direct link to Resources and Data Sources") The `lifecycle` block inside a `resource` or `data` block can include both `precondition` and `postcondition` blocks. * OpenTofu evaluates `precondition` blocks after evaluating existing `count` and `for_each` arguments. This lets OpenTofu evaluate the precondition separately for each instance and then make `each.key`, `count.index`, etc. available to those conditions. OpenTofu also evaluates preconditions before evaluating the resource's configuration arguments. Preconditions can take precedence over argument evaluation errors. * OpenTofu evaluates `postcondition` blocks after planning and applying changes to a managed resource, or after reading from a data source. Postcondition failures prevent changes to other resources that depend on the failing resource. In most cases, we do not recommend including both a `data` block and a `resource` block that both represent the same object in the same configuration. Doing so can prevent OpenTofu from understanding that the `data` block result can be affected by changes in the `resource` block. However, when you need to check a result of a `resource` block that the resource itself does not directly export, you can use a `data` block to check that object safely as long as you place the check as a direct `postcondition` of the `data` block. This tells OpenTofu that the `data` block is serving as a check of an object defined elsewhere, allowing OpenTofu to perform actions in the correct order. #### Outputs[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#outputs "Direct link to Outputs") An `output` block can include a `precondition` block. Preconditions can serve a symmetrical purpose to input variable `validation` blocks. Whereas input variable validation checks assumptions the module makes about its inputs, preconditions check guarantees that the module makes about its outputs. You can use preconditions to prevent OpenTofu from saving an invalid new output value in the state. You can also use them to preserve a valid output value from the previous apply, if applicable. OpenTofu evaluates output value preconditions before evaluating the `value` expression to finalize the result. Preconditions can take precedence over potential errors in the `value` expression. ### Examples[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#examples "Direct link to Examples") The following example shows use cases for preconditions and postconditions. The preconditions and postconditions declare the following assumptions and guarantees. * **The AMI ID must refer to an AMI that contains an operating system for the `x86_64` architecture.** The precondition would detect if the caller accidentally built an AMI for a different architecture, which may not be able to run the software this virtual machine is intended to host. * **The EC2 instance must be allocated a public DNS hostname.** In Amazon Web Services, EC2 instances are assigned public DNS hostnames only if they belong to a virtual network configured in a certain way. The postcondition would detect if the selected virtual network is not configured correctly, prompting the user to debug the network settings. * **The EC2 instance will have an encrypted root volume.** The precondition ensures that the root volume is encrypted, even though the software running in this EC2 instance would probably still operate as expected on an unencrypted volume. This lets OpenTofu produce an error immediately, before any other components rely on the new EC2 instance. Code Block data "aws_ami" "example" { owners = ["amazon"] filter { name = "image-id" values = ["ami-abc123"] }}resource "aws_instance" "example" { instance_type = "t3.micro" ami = data.aws_ami.example.id lifecycle { # The AMI ID must refer to an AMI that contains an operating system # for the `x86_64` architecture. precondition { condition = data.aws_ami.example.architecture == "x86_64" error_message = "The selected AMI must be for the x86_64 architecture." } # The EC2 instance must be allocated a public DNS hostname. postcondition { condition = self.public_dns != "" error_message = "EC2 instance must be in a VPC that has public DNS hostnames enabled." } }}data "aws_ebs_volume" "example" { # Use data resources that refer to other resources to # load extra data that isn't directly exported by a resource. # # Read the details about the root storage volume for the EC2 instance # declared by aws_instance.example, using the exported ID. filter { name = "volume-id" values = [aws_instance.example.root_block_device.volume_id] } # Whenever a data resource is verifying the result of a managed resource # declared in the same configuration, you MUST write the checks as # postconditions of the data resource. This ensures OpenTofu will wait # to read the data resource until after any changes to the managed resource # have completed. lifecycle { # The EC2 instance will have an encrypted root volume. postcondition { condition = self.encrypted error_message = "The server's root volume is not encrypted." } }}output "api_base_url" { value = "https://${aws_instance.example.private_dns}:8433/"} ### Choosing Between Preconditions and Postconditions[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#choosing-between-preconditions-and-postconditions "Direct link to Choosing Between Preconditions and Postconditions") You can often implement a validation check as either a postcondition of the resource producing the data or as a precondition of a resource or output value using the data. To decide which is most appropriate, consider whether the check is representing either an assumption or a guarantee. #### Use Preconditions for Assumptions[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#use-preconditions-for-assumptions "Direct link to Use Preconditions for Assumptions") An assumption is a condition that must be true in order for the configuration of a particular resource to be usable. For example, an `aws_instance` configuration can have the assumption that the given AMI will always be configured for the `x86_64` CPU architecture. We recommend using preconditions for assumptions, so that future maintainers can find them close to the other expressions that rely on that condition. This lets them understand more about what that resource is intended to allow. #### Use Postconditions for Guarantees[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#use-postconditions-for-guarantees "Direct link to Use Postconditions for Guarantees") A guarantee is a characteristic or behavior of an object that the rest of the configuration should be able to rely on. For example, an `aws_instance` configuration can have the guarantee that an EC2 instance will be running in a network that assigns it a private DNS record. We recommend using postconditions for guarantees, so that future maintainers can find them close to the resource configuration that is responsible for implementing those guarantees. This lets them more easily determine which behaviors they should preserve when changing the configuration. #### Additional Decision Factors[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#additional-decision-factors "Direct link to Additional Decision Factors") You should also consider the following questions when creating preconditions and postconditions. * Which resource or output value would be most helpful to report in the error message? OpenTofu will always report errors in the location where the condition was declared. * Which approach is more convenient? If a particular resource has many dependencies that all make an assumption about that resource, it can be pragmatic to declare that once as a post-condition of the resource, rather than declaring it many times as preconditions on each of the dependencies. * Is it helpful to declare the same or similar conditions as both preconditions and postconditions? This can be useful if the postcondition is in a different module than the precondition because it lets the modules verify one another as they evolve independently. Checks with Assertions[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#checks-with-assertions "Direct link to Checks with Assertions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ [Check blocks](https://opentofu.org/docs/v1.10/language/checks/) can validate your infrastructure outside the usual resource lifecycle. You can add custom conditions via `assert` blocks, which execute at the end of the plan and apply stages and produce warnings to notify you of problems within your infrastructure. You can add one or more `assert` blocks within a `check` block to verify custom conditions. Each assertion requires a [`condition` argument](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#condition-expressions) , a boolean expression that should return `true` if the intended assumption or guarantee is fulfilled or `false` if it does not. Your `condition` expression can refer to any resource, data source, or variable available to the surrounding `check` block. The following example uses a check block with an assertion to verify the OpenTofu website is healthy. Code Block check "health_check" { data "http" "opentofu_org" { url = "https://www.opentofu.org" } assert { condition = data.http.opentofu_org.status_code == 200 error_message = "${data.http.opentofu_org.url} returned an unhealthy status code" }} If the condition evaluates to `false`, OpenTofu produces an [error message](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#error-messages) that includes the result of the `error_message` expression. If you declare multiple assertions, OpenTofu returns error messages for all failed conditions. ### Continuous Validation in a cloud backend[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#continuous-validation-in-a-cloud-backend "Direct link to Continuous Validation in a cloud backend") A cloud backend can automatically check whether the checks in a workspace’s configuration continue to pass after OpenTofu provisions the infrastructure. For example, you can write a `check` to continuously monitor the validity of an API gateway certificate. Continuous validation alerts you when the condition fails, so you can update the certificate and avoid errors the next time you want to update your infrastructure. Condition Expressions[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#condition-expressions "Direct link to Condition Expressions") --------------------------------------------------------------------------------------------------------------------------------------------------------------- Check assertions, input variable validation, preconditions, and postconditions all require a `condition` argument. This is a boolean expression that should return `true` if the intended assumption or guarantee is fulfilled or `false` if it does not. You can use any of OpenTofu's built-in functions or language operators in a condition as long as the expression is valid and returns a boolean result. The following language features are particularly useful when writing condition expressions. ### Logical Operators[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#logical-operators "Direct link to Logical Operators") Use the logical operators `&&` (AND), `||` (OR), and `!` (NOT) to combine multiple conditions together. Code Block condition = var.name != "" && lower(var.name) == var.name You can also use arithmetic operators (e.g. `a + b`), equality operators (eg., `a == b`) and comparison operators (e.g., `a < b`). Refer to [Arithmetic and Logical Operators](https://opentofu.org/docs/v1.10/language/expressions/operators/) for details. ### `contains` Function[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#contains-function "Direct link to contains-function") Use the [`contains` function](https://opentofu.org/docs/v1.10/language/functions/contains/) to test whether a given value is one of a set of predefined valid values. Code Block condition = contains(["STAGE", "PROD"], var.environment) ### `length` Function[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#length-function "Direct link to length-function") Use the [`length` function](https://opentofu.org/docs/v1.10/language/functions/length/) to test a collection's length and require a non-empty list or map. Code Block condition = length(var.items) != 0 This is a better approach than directly comparing with another collection using `==` or `!=`. This is because the comparison operators can only return `true` if both operands have exactly the same type, which is often ambiguous for empty collections. ### `for` Expressions[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#for-expressions "Direct link to for-expressions") Use [`for` expressions](https://opentofu.org/docs/v1.10/language/expressions/for/) in conjunction with the functions `alltrue` and `anytrue` to test whether a condition holds for all or for any elements of a collection. Code Block condition = alltrue([ for v in var.instances : contains(["t2.micro", "m3.medium"], v.type) ]) ### `can` Function[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#can-function "Direct link to can-function") Use the [`can` function](https://opentofu.org/docs/v1.10/language/functions/can/) to concisely use the validity of an expression as a condition. It returns `true` if its given expression evaluates successfully and `false` if it returns any error, so you can use various other functions that typically return errors as a part of your condition expressions. For example, you can use `can` with `regex` to test if a string matches a particular pattern because `regex` returns an error when given a non-matching string. Code Block condition = can(regex("^[a-z]+$", var.name)) You can also use `can` with the type conversion functions to test whether a value is convertible to a type or type constraint. Code Block # This remote output value must have a value that can # be used as a string, which includes strings themselves # but also allows numbers and boolean values. condition = can(tostring(data.terraform_remote_state.example.outputs["name"])) Code Block # This remote output value must be convertible to a list # type of with element type. condition = can(tolist(data.terraform_remote_state.example.outputs["items"])) You can also use `can` with attribute access or index operators to test whether a collection or structural value has a particular element or index. Code Block # var.example must have an attribute named "foo" condition = can(var.example.foo) Code Block # var.example must be a sequence with at least one element condition = can(var.example[0]) # (although it would typically be clearer to write this as a # test like length(var.example) > 0 to better represent the # intent of the condition.) ### `self` Object[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#self-object "Direct link to self-object") Use the `self` object in postcondition blocks to refer to attributes of the instance under evaluation. Code Block resource "aws_instance" "example" { instance_type = "t2.micro" ami = "ami-abc123" lifecycle { postcondition { condition = self.instance_state == "running" error_message = "EC2 instance must be running." } }} ### `each` and `count` Objects[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#each-and-count-objects "Direct link to each-and-count-objects") In blocks where [`for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) or [`count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) are set, use `each` and `count` objects to refer to other resources that are expanded in a chain. Code Block variable "vpc_cidrs" { type = set(string)}data "aws_vpc" "example" { for_each = var.vpc_cidrs filter { name = "cidr" values = [each.key] }}resource "aws_internet_gateway" "example" { for_each = data.aws_vpc.example vpc_id = each.value.id lifecycle { precondition { condition = data.aws_vpc.example[each.key].state == "available" error_message = "VPC ${each.key} must be available." } }} Error Messages[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#error-messages "Direct link to Error Messages") ------------------------------------------------------------------------------------------------------------------------------------------ Input variable validations, preconditions, and postconditions all must include the `error_message` argument. This contains the text that OpenTofu will include as part of error messages when it detects an unmet condition. Code Block Error: Resource postcondition failed with data.aws_ami.example, on ec2.tf line 19, in data "aws_ami" "example": 72: condition = self.tags["Component"] == "nomad-server" |---------------- | self.tags["Component"] is "consul-server"The selected AMI must be tagged with the Component value "nomad-server". The `error_message` argument can be any expression that evaluates to a string. This includes literal strings, heredocs, and template expressions. You can use the [`format` function](https://opentofu.org/docs/v1.10/language/functions/format/) to convert items of `null`, `list`, or `map` types into a formatted string. Multi-line error messages are supported, and lines with leading whitespace will not be word wrapped. We recommend writing error messages as one or more full sentences in a style similar to OpenTofu's own error messages. OpenTofu will show the message alongside the name of the resource that detected the problem and any external values included in the condition expression. Conditions Checked Only During Apply[​](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#conditions-checked-only-during-apply "Direct link to Conditions Checked Only During Apply") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ OpenTofu evaluates custom conditions as early as possible. Input variable validations can only refer to the variable value, so OpenTofu always evaluates them immediately. Check assertions, preconditions, and postconditions depend on OpenTofu evaluating whether the value(s) associated with the condition are known before or after applying the configuration. * **Known before apply:** OpenTofu checks the condition during the planning phase. For example, OpenTofu can know the value of an image ID during planning as long as it is not generated from another resource. * **Known after apply:** OpenTofu delays checking that condition until the apply phase. For example, AWS only assigns the root volume ID when it starts an EC2 instance, so OpenTofu cannot know this value until apply. During the apply phase, a failed _precondition_ will prevent OpenTofu from implementing planned actions for the associated resource. However, a failed _postcondition_ will halt processing after OpenTofu has already implemented these actions. The failed postcondition prevents any further downstream actions that rely on the resource, but does not undo the actions OpenTofu has already taken. OpenTofu typically has less information during the initial creation of a full configuration than when applying subsequent changes. Therefore, OpenTofu may check conditions during apply for initial creation and then check them during planning for subsequent updates. * [Selecting a Custom Condition for your use case](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#selecting-a-custom-condition-for-your-use-case) * [Input Variable Validation](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#input-variable-validation) * [Preconditions and Postconditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#preconditions-and-postconditions) * [Usage](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#usage) * [Examples](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#examples) * [Choosing Between Preconditions and Postconditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#choosing-between-preconditions-and-postconditions) * [Checks with Assertions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#checks-with-assertions) * [Continuous Validation in a cloud backend](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#continuous-validation-in-a-cloud-backend) * [Condition Expressions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#condition-expressions) * [Logical Operators](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#logical-operators) * [`contains` Function](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#contains-function) * [`length` Function](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#length-function) * [`for` Expressions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#for-expressions) * [`can` Function](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#can-function) * [`self` Object](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#self-object) * [`each` and `count` Objects](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#each-and-count-objects) * [Error Messages](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#error-messages) * [Conditions Checked Only During Apply](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#conditions-checked-only-during-apply) --- # Generating configuration | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Generating configuration ======================== Experimental Configuration generation is available in OpenTofu v1.6 as an experimental feature. Later minor versions may contain changes to the formatting of generated configuration and behavior of the `tofu plan` command using the `-generate-config-out` flag. OpenTofu can generate code for the resources you define in [`import` blocks](https://opentofu.org/docs/v1.10/language/import/) that do not already exist in your configuration. OpenTofu produces HCL to act as a template that contains OpenTofu's best guess at the appropriate value for each resource argument. Starting with OpenTofu's generated HCL, we recommend iterating to find your ideal configuration by removing some attributes, adjusting the value of others, and rearranging `resource` blocks into files and modules as appropriate. To generate configuration, run `tofu plan` with the `-generate-config-out` flag and supply a new file path. Do not supply a path to an existing file, or OpenTofu throws an error. Code Block $ tofu plan -generate-config-out=generated_resources.tf If any resources targeted by an `import` block do not exist in your configuration, OpenTofu then generates and writes configuration for those resources in `generated_resources.tf`. Workflow[​](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#workflow "Direct link to Workflow") -------------------------------------------------------------------------------------------------------------------------- The workflow for generating configuration is similar to the [`import` block workflow](https://opentofu.org/docs/v1.10/language/import/#plan-and-apply-an-import) , with the extra step of generating configuration during the planning stage. You can then review and modify the generated configuration before applying. ### 1\. Add the `import` block[​](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#1-add-the-import-block "Direct link to 1-add-the-import-block") Add an `import` block to your configuration. This `import` block can be in a separate file (e.g., `import.tf`) or an existing configuration file. Code Block import { to = aws_iot_thing.bar id = "foo"} The import block's `to` argument points to the address a `resource` will have in your state file. If a resource address in your state matches an `import` block's `to` argument, OpenTofu attempts to import into that resource. In future planning, OpenTofu knows it doesn't need to generate configuration for resources that already exist in your state. The import block's `id` argument uses that resource's [import ID](https://opentofu.org/docs/v1.10/language/import/#import-id) . If your configuration does not contain other resources for your selected provider, you must add a `provider` block to inform OpenTofu which provider it should use to generate configuration. Otherwise, OpenTofu displays an error if it can not determine which provider to use. If you add a new `provider` block to your configuration, you must run `tofu init` again. ### 2\. Plan and generate configuration[​](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#2-plan-and-generate-configuration "Direct link to 2. Plan and generate configuration") To instruct OpenTofu to generate configuration for the `import` blocks you defined, run `tofu plan` with the `-generate-config-out=` flag and a new file path. OpenTofu displays its plan for importing your resource and the file where OpenTofu generated configuration based on this plan. Code Block $ tofu plan -generate-config-out=generated.tfaws_iot_thing.bar: Preparing import... [id=foo]aws_iot_thing.bar: Refreshing state... [id=foo]OpenTofu will perform the following actions: # aws_iot_thing.bar will be imported # (config will be generated) resource "aws_iot_thing" "bar" { arn = "arn:aws:iot:eu-west-1:1234567890:thing/foo" attributes = {} default_client_id = "foo" id = "foo" name = "foo" version = 1 }Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.β•·β”‚ Warning: Config generation is experimentalβ”‚ β”‚ Generating configuration during import is currently experimental, and the generated configuration format may change in future versions.╡──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────OpenTofu has generated configuration and written it to generated.tf. Please review the configuration and edit it as necessary before adding it to version control. ### 3\. Review generated configuration[​](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#3-review-generated-configuration "Direct link to 3. Review generated configuration") The example above instructs OpenTofu to generate configuration in a file named `generated.tf`. The below code is an example of a `generated.tf` file. Code Block resource aws_iot_thing "bar" { name = "foo"} Review the generated configuration and update it as needed. You may wish to move the generated configuration to another file, add or remove resource arguments, or update it to reference input variables or other resources in your configuration. ### 4\. Apply[​](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#4-apply "Direct link to 4. Apply") Run `tofu apply` to import your infrastructure. Code Block $ tofu applyaws_iot_thing.bar: Preparing import... [id=foo]aws_iot_thing.bar: Refreshing state... [id=foo]OpenTofu will perform the following actions: # aws_iot_thing.bar will be imported resource "aws_iot_thing" "bar" { arn = "arn:aws:iot:eu-west-1:1234567890:thing/foo" attributes = {} default_client_id = "foo" id = "foo" name = "foo" version = 1 }Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.aws_iot_thing.bar: Importing... [id=foo]aws_iot_thing.bar: Import complete [id=foo]Apply complete! Resources: 1 imported, 0 added, 0 changed, 0 destroyed. Commit your new resource configuration to your version control system. Limitations[​](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#limitations "Direct link to Limitations") ----------------------------------------------------------------------------------------------------------------------------------- ### Conflicting resource arguments[​](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#conflicting-resource-arguments "Direct link to Conflicting resource arguments") OpenTofu generates configuration for importable resources during a plan by requesting values for resource attributes from the provider. For certain resources with complex schemas, OpenTofu may not be able to construct a valid configuration from these values. OpenTofu will display an error like the one below if it does not receive values for resource attributes while generating configuration. Code Block $ tofu plan -generate-config-out=generated.tfβ•·β”‚ Error: Conflicting configuration argumentsβ”‚ β”‚ with aws_instance.ubuntu,β”‚ on g.tf line 20, in resource "aws_instance" "ubuntu":β”‚ 20: ipv6_address_count = 0β”‚ β”‚ "ipv6_address_count": conflicts with ipv6_addressesβ•΅ In the example above, OpenTofu still generates configuration and writes it to `generated.tf`. This error stems from a conflict between the `ipv6_address_count` and `ipv6_addresses` arguments. The resource supports both of these arguments, but you must choose only one when configuring the resource. You could fix the error by removing one of these two arguments, then running `tofu plan` again to check that there are no further issues. * [Workflow](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#workflow) * [1\. Add the `import` block](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#1-add-the-import-block) * [2\. Plan and generate configuration](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#2-plan-and-generate-configuration) * [3\. Review generated configuration](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#3-review-generated-configuration) * [4\. Apply](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#4-apply) * [Limitations](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#limitations) * [Conflicting resource arguments](https://opentofu.org/docs/v1.10/language/import/generating-configuration/#conflicting-resource-arguments) --- # Built-in Provider | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/providers/builtin/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Built-in Provider ================= Most providers are distributed separately as plugins, but there is one provider that is built into OpenTofu itself. This provider enables the [the `terraform_remote_state` data source](https://opentofu.org/docs/v1.10/language/state/remote-state-data/) . Because this provider is built in to OpenTofu, you don't need to declare it in the `required_providers` block in order to use its features (except provider functions). It has a special provider source address, which is `terraform.io/builtin/terraform`. This address may sometimes appear in OpenTofu's error messages and other output in order to unambiguously refer to the built-in provider, as opposed to a hypothetical third-party provider with the type name "terraform". There is also an existing provider with the source address `hashicorp/terraform`, which is an older version of the now-built-in provider. `hashicorp/terraform` is not compatible with OpenTofu and should never be declared in a `required_providers` block. Functions[​](https://opentofu.org/docs/v1.10/language/providers/builtin/#functions "Direct link to Functions") --------------------------------------------------------------------------------------------------------------- The built-in provider has additional functions, which can be called after declaring the provider in the `required_providers` block. Code Block terraform { required_providers { terraform = { source = "terraform.io/builtin/terraform" } }} ### decode\_tfvars[​](https://opentofu.org/docs/v1.10/language/providers/builtin/#decode_tfvars "Direct link to decode_tfvars") `decode_tfvars` takes the content of the .tfvars file as a string input and returns a decoded object. Code Block locals { content = file("./example_file.tfvars") decoded = provider::terraform::decode_tfvars(local.content) # Returns object} ### encode\_tfvars[​](https://opentofu.org/docs/v1.10/language/providers/builtin/#encode_tfvars "Direct link to encode_tfvars") `encode_tfvars` takes an object and returns the string representation of the object that can be used as the content of the .tfvars file. Code Block locals { object = { key1 = "value1" key2 = "value2" } encoded = provider::terraform::encode_tfvars(local.object) # Returns string} The keys in the object need to be [valid identifiers](https://opentofu.org/docs/v1.10/language/syntax/configuration/#identifiers) . ### encode\_expr[​](https://opentofu.org/docs/v1.10/language/providers/builtin/#encode_expr "Direct link to encode_expr") `encode_expr` takes an arbitrary [expression](https://opentofu.org/docs/v1.10/language/expressions/) and converts it into a string with valid OpenTofu syntax. Code Block locals { expression = { key1 = "value1" key2 = "value2" } encoded = provider::terraform::encode_expr(local.expression) # Returns string} * [Functions](https://opentofu.org/docs/v1.10/language/providers/builtin/#functions) * [decode\_tfvars](https://opentofu.org/docs/v1.10/language/providers/builtin/#decode_tfvars) * [encode\_tfvars](https://opentofu.org/docs/v1.10/language/providers/builtin/#encode_tfvars) * [encode\_expr](https://opentofu.org/docs/v1.10/language/providers/builtin/#encode_expr) --- # Publishing Modules | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/modules/develop/publish/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Publishing Modules ================== If you've built a module that you intend to be reused, we recommend [publishing the module](https://github.com/opentofu/registry/issues/new/choose) on the [Public OpenTofu Registry](https://registry.opentofu.org/) . This will version your module, generate documentation, and more. Published modules can be easily consumed by OpenTofu, and users can [constrain module versions](https://opentofu.org/docs/v1.10/language/modules/syntax/#version) for safe and predictable updates. The following example shows how a caller might use a module from the Module Registry: Code Block module "consul" { source = "hashicorp/consul/aws"} If you do not wish to publish your modules in the public registry, you can instead use a [private registry](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/) to get the same benefits. We welcome contributions of modules from our community members, partners, and customers. Our ecosystem is made richer by each new module created or an existing one updated, as they reflect the wide range of experience and technical requirements of the community that uses them. Our cloud provider partners often seek to develop specific modules for popular or challenging use cases on their platform and utilize them as valuable learning experiences to empathize with their users. Similarly, our community module developers incorporate a variety of opinions and use cases from the broader OpenTofu community. Both types of modules have their place in the registry, accessible to practitioners who can decide which modules best fit their requirements. Distribution via other sources[​](https://opentofu.org/docs/v1.10/language/modules/develop/publish/#distribution-via-other-sources "Direct link to Distribution via other sources") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Although the registry is the native mechanism for distributing re-usable modules, OpenTofu can also install modules from [various other sources](https://opentofu.org/docs/v1.10/language/modules/sources/) . The alternative sources do not support the first-class versioning mechanism, but some sources have their own mechanisms for selecting particular VCS commits, etc. We recommend that modules distributed via other protocols still use the [standard module structure](https://opentofu.org/docs/v1.10/language/modules/develop/structure/) so that they can be used in a similar way as a registry module or be published on the registry at a later time. * [Distribution via other sources](https://opentofu.org/docs/v1.10/language/modules/develop/publish/#distribution-via-other-sources) --- # Creating Modules | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/modules/develop/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Creating Modules ================ A _module_ is a container for multiple resources that are used together. You can use modules to create lightweight abstractions, so that you can describe your infrastructure in terms of its architecture, rather than directly in terms of physical objects. The `.tf` and/or `.tofu` files in your working directory when you run [`tofu plan`](https://opentofu.org/docs/v1.10/cli/commands/plan/) or [`tofu apply`](https://opentofu.org/docs/v1.10/cli/commands/apply/) together form the _root_ module. That module may [call other modules](https://opentofu.org/docs/v1.10/language/modules/syntax/#calling-a-child-module) and connect them together by passing output values from one to input values of another. To learn how to _use_ modules, see [the Modules configuration section](https://opentofu.org/docs/v1.10/language/modules/) . This section is about _creating_ re-usable modules that other configurations can include using `module` blocks. Module structure[​](https://opentofu.org/docs/v1.10/language/modules/develop/#module-structure "Direct link to Module structure") ---------------------------------------------------------------------------------------------------------------------------------- Re-usable modules are defined using all of the same [configuration language](https://opentofu.org/docs/v1.10/language/) concepts we use in root modules. Most commonly, modules use: * [Input variables](https://opentofu.org/docs/v1.10/language/values/variables/) to accept values from the calling module. * [Output values](https://opentofu.org/docs/v1.10/language/values/outputs/) to return results to the calling module, which it can then use to populate arguments elsewhere. * [Resources](https://opentofu.org/docs/v1.10/language/resources/) to define one or more infrastructure objects that the module will manage. To define a module, create a new directory for it and place one or more `.tf` files inside just as you would do for a root module. OpenTofu can load modules either from local relative paths or from remote repositories; if a module will be re-used by lots of configurations you may wish to place it in its own version control repository. Modules can also call other modules using a `module` block, but we recommend keeping the module tree relatively flat and using [module composition](https://opentofu.org/docs/v1.10/language/modules/develop/composition/) as an alternative to a deeply-nested tree of modules, because this makes the individual modules easier to re-use in different combinations. When to write a module[​](https://opentofu.org/docs/v1.10/language/modules/develop/#when-to-write-a-module "Direct link to When to write a module") ---------------------------------------------------------------------------------------------------------------------------------------------------- In principle any combination of resources and other constructs can be factored out into a module, but over-using modules can make your overall OpenTofu configuration harder to understand and maintain, so we recommend moderation. A good module should raise the level of abstraction by describing a new concept in your architecture that is constructed from resource types offered by providers. For example, `aws_instance` and `aws_elb` are both resource types belonging to the AWS provider. You might use a module to represent the higher-level concept "[HashiCorp Consul](https://www.consul.io/) cluster running in AWS" which happens to be constructed from these and other AWS provider resources. We _do not_ recommend writing modules that are just thin wrappers around single other resource types. If you have trouble finding a name for your module that isn't the same as the main resource type inside it, that may be a sign that your module is not creating any new abstraction and so the module is adding unnecessary complexity. Just use the resource type directly in the calling module instead. Refactoring module resources[​](https://opentofu.org/docs/v1.10/language/modules/develop/#refactoring-module-resources "Direct link to Refactoring module resources") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can include [refactoring blocks](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/) to record how resource names and module structure have changed from previous module versions. OpenTofu uses that information during planning to reinterpret existing objects as if they had been created at the corresponding new addresses, eliminating a separate workflow step to replace or migrate existing objects. * [Module structure](https://opentofu.org/docs/v1.10/language/modules/develop/#module-structure) * [When to write a module](https://opentofu.org/docs/v1.10/language/modules/develop/#when-to-write-a-module) * [Refactoring module resources](https://opentofu.org/docs/v1.10/language/modules/develop/#refactoring-module-resources) --- # The depends_on Meta-Argument | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/meta-arguments/depends_on/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page The `depends_on` Meta-Argument ============================== Use the `depends_on` meta-argument to handle hidden resource or module dependencies that OpenTofu cannot automatically infer. You only need to explicitly specify a dependency when a resource or module relies on another resource's behavior but does not access any of that resource's data in its arguments. Processing and Planning Consequences[​](https://opentofu.org/docs/v1.10/language/meta-arguments/depends_on/#processing-and-planning-consequences "Direct link to Processing and Planning Consequences") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The `depends_on` meta-argument instructs OpenTofu to complete all actions on the dependency object (including Read actions) before performing actions on the object declaring the dependency. When the dependency object is an entire module, `depends_on` affects the order in which OpenTofu processes all of the resources and data sources associated with that module. Refer to [Resource Dependencies](https://opentofu.org/docs/v1.10/language/resources/behavior/#resource-dependencies) and [Data Resource Dependencies](https://opentofu.org/docs/v1.10/language/data-sources/#data-resource-dependencies) for more details. You should use `depends_on` as a last resort because it can cause OpenTofu to create more conservative plans that replace more resources than necessary. For example, OpenTofu may treat more values as unknown β€œ(known after apply)” because it is uncertain what changes will occur on the upstream object. This is especially likely when you use `depends_on` for modules. Instead of `depends_on`, we recommend using [expression references](https://opentofu.org/docs/v1.10/language/expressions/references/) to imply dependencies when possible. Expression references let OpenTofu understand which value the reference derives from and avoid planning changes if that particular value hasn’t changed, even if other parts of the upstream object have planned changes. Usage[​](https://opentofu.org/docs/v1.10/language/meta-arguments/depends_on/#usage "Direct link to Usage") ----------------------------------------------------------------------------------------------------------- You can use the `depends_on` meta-argument in `module` blocks and in all `resource` blocks, regardless of resource type. It requires a list of references to other resources or child modules in the same calling module. This list cannot include arbitrary expressions because the `depends_on` value must be known before OpenTofu knows resource relationships and thus before it can safely evaluate expressions. We recommend always including a comment that explains why using `depends_on` is necessary. The following example uses `depends_on` to handle a "hidden" dependency on the `aws_iam_instance_profile.example`. Code Block resource "aws_iam_role" "example" { name = "example" # assume_role_policy is omitted for brevity in this example. Refer to the # documentation for aws_iam_role for a complete example. assume_role_policy = "..."}resource "aws_iam_instance_profile" "example" { # Because this expression refers to the role, OpenTofu can infer # automatically that the role must be created first. role = aws_iam_role.example.name}resource "aws_iam_role_policy" "example" { name = "example" role = aws_iam_role.example.name policy = jsonencode({ "Statement" = [{ # This policy allows software running on the EC2 instance to # access the S3 API. "Action" = "s3:*", "Effect" = "Allow", }], })}resource "aws_instance" "example" { ami = "ami-a1b2c3d4" instance_type = "t2.micro" # OpenTofu can infer from this that the instance profile must # be created before the EC2 instance. iam_instance_profile = aws_iam_instance_profile.example # However, if software running in this EC2 instance needs access # to the S3 API in order to boot properly, there is also a "hidden" # dependency on the aws_iam_role_policy that OpenTofu cannot # automatically infer, so it must be declared explicitly: depends_on = [ aws_iam_role_policy.example ]} * [Processing and Planning Consequences](https://opentofu.org/docs/v1.10/language/meta-arguments/depends_on/#processing-and-planning-consequences) * [Usage](https://opentofu.org/docs/v1.10/language/meta-arguments/depends_on/#usage) --- # Provisioners Without a Resource | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/resources/provisioners/null_resource/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provisioners Without a Resource =============================== If you need to run provisioners that aren't directly associated with a specific resource, you can associate them with a `terraform_data`. Instances of [`terraform_data`](https://opentofu.org/docs/v1.10/language/resources/tf-data/) are treated like normal resources, but they don't do anything. Like with any other resource type, you can configure [provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/) and [connection details](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/) on a `terraform_data` resource. You can also use its `input` argument, `triggers_replace` argument, and any meta-arguments to control exactly where in the dependency graph its provisioners will run. Important Use provisioners as a last resort. There are better alternatives for most situations. Refer to [Declaring Provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/) for more details. Example usage[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/null_resource/#example-usage "Direct link to Example usage") ---------------------------------------------------------------------------------------------------------------------------------------------- Code Block resource "aws_instance" "cluster" { count = 3 # ...}resource "terraform_data" "cluster" { # Replacement of any instance of the cluster requires re-provisioning triggers_replace = aws_instance.cluster.[*].id # Bootstrap script can run on any instance of the cluster # So we just choose the first in this case connection { host = aws_instance.cluster.[0].public_ip } provisioner "remote-exec" { # Bootstrap script called with private_ip of each node in the cluster inline = [ "bootstrap-cluster.sh ${join(" ", aws_instance.cluster.*.private_ip)}", ] }} * [Example usage](https://opentofu.org/docs/v1.10/language/resources/provisioners/null_resource/#example-usage) --- # OpenTofu CLI Documentation | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu CLI Documentation ========================== This is the documentation for OpenTofu CLI. It is relevant to anyone working with OpenTofu's CLI-based workflows; this includes people who use OpenTofu CLI by itself, as well as those who use OpenTofu CLI in conjunction with [TACOS](https://opentofu.org/docs/v1.11/intro/tacos/) (TF Automation and Collaboration Software). Notably, this documentation does not cover the syntax and usage of the OpenTofu language. For that, see the [OpenTofu Language Documentation](https://opentofu.org/docs/v1.11/language/) . --- # The Resource provider Meta-Argument | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/meta-arguments/resource-provider/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) The Resource `provider` Meta-Argument ===================================== The `provider` meta-argument specifies which provider instance is responsible for managing each instance of a resource, overriding OpenTofu's default behavior of [automatically selecting a default provider configuration](https://opentofu.org/docs/v1.10/language/providers/configuration/#default-provider-configurations) . As described in [Provider Configuration](https://opentofu.org/docs/v1.10/language/providers/configuration/) , you can optionally declare multiple configurations for a single provider, or multiple dynamic instances of a single provider configuration, such as when managing resources across different regions when using a provider which forces only a single region per provider instance. By default, OpenTofu interprets the initial word in the resource type name (separated by underscores) as the local name of a provider, and uses that provider's default configuration. For example, the resource type `google_compute_instance` is associated automatically with the default configuration for the provider whose local name in the current module is `google`. Using the `provider` meta-argument you can select an alternate provider configuration for a resource: Code Block # default configurationprovider "google" { region = "us-central1"}# alternate configuration, whose alias is "europe"provider "google" { alias = "europe" region = "europe-west1"}resource "google_compute_instance" "example" { # This "provider" meta-argument selects the google provider # configuration whose alias is "europe", rather than the # default configuration. provider = google.europe # ...} If you select a provider configuration that uses `for_each` then you must also dynamically select a different instance of the provider configuration for each instance of the resource by including an instance key expression in brackets: Code Block variable "aws_regions" { type = map(object({ vpc_cidr_block = string }))}provider "aws" { alias = "by_region" for_each = var.aws_regions region = each.key}resource "aws_vpc" "private" { # This expression filters var.aws_regions to include only # the elements whose value is not null. Refer to the # warning in the text below for more information. for_each = { for region, config in var.aws_regions : region => config if config != null } provider = aws.by_region[each.key] cidr_block = each.value.vpc_cidr_block} You can find more detail on the syntax used with the `provider` argument in [Referring to Provider Instances](https://opentofu.org/docs/v1.10/language/providers/configuration/#referring-to-provider-instances) . Warning **The `for_each` expression for a resource must not exactly match the `for_each` expression for its associated provider configuration.** OpenTofu uses a provider instance to plan and apply _all_ actions related to a resource instance, including destroying a resource instance that has been removed from the configuration. Therefore the provider instance associated with any resource instance must always remain in the configuration for at least one more plan/apply round after the resource instance has been removed, or OpenTofu will fail to plan to destroy the resource instance. You can find more information on this constraint in [Referring to Provider Instances](https://opentofu.org/docs/v1.10/language/providers/configuration/#referring-to-provider-instances) . --- # Resources | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/resources/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Resources ========= _Resources_ are the most important element in the OpenTofu language. Each resource block describes one or more infrastructure objects, such as virtual networks, compute instances, or higher-level components such as DNS records. * [Resource Blocks](https://opentofu.org/docs/v1.10/language/resources/syntax/) documents the syntax for declaring resources. * [Resource Behavior](https://opentofu.org/docs/v1.10/language/resources/behavior/) explains in more detail how OpenTofu handles resource declarations when applying a configuration. * The Meta-Arguments section documents special arguments that can be used with every resource type, including [`depends_on`](https://opentofu.org/docs/v1.10/language/meta-arguments/depends_on/) , [`count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) , [`for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) , [`provider`](https://opentofu.org/docs/v1.10/language/meta-arguments/resource-provider/) , and [`lifecycle`](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/) . * [Provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/) documents configuring post-creation actions for a resource using the `provisioner` and `connection` blocks. Since provisioners are non-declarative and potentially unpredictable, we strongly recommend that you treat them as a last resort. --- # Modules | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/modules/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Modules ======= _Modules_ are containers for multiple resources that are used together. A module consists of a collection of `.tf`, `.tofu`, `.tf.json`, and/or `.tofu.json` files that are kept together in a directory. Modules are the main way to package and reuse resource configurations with OpenTofu. The Root Module[​](https://opentofu.org/docs/v1.10/language/modules/#the-root-module "Direct link to The Root Module") ----------------------------------------------------------------------------------------------------------------------- Every OpenTofu configuration has at least one module, known as its _root module_, which consists of the resources defined in the `.tf` or `.tofu` files in the main working directory. Child Modules[​](https://opentofu.org/docs/v1.10/language/modules/#child-modules "Direct link to Child Modules") ----------------------------------------------------------------------------------------------------------------- An OpenTofu module (usually the root module of a configuration) can _call_ other modules to include their resources into the configuration. A module that has been called by another module is often referred to as a _child module._ Child modules can be called multiple times within the same configuration, and multiple configurations can use the same child module. Published Modules[​](https://opentofu.org/docs/v1.10/language/modules/#published-modules "Direct link to Published Modules") ----------------------------------------------------------------------------------------------------------------------------- In addition to modules from the local filesystem, OpenTofu can load modules from a public or private registry. This makes it possible to publish modules for others to use, and to use modules that others have published. The [Public OpenTofu Registry](https://github.com/opentofu/registry/tree/main/modules) hosts a broad collection of publicly available OpenTofu modules for configuring many kinds of common infrastructure. These modules are free to use, and OpenTofu can download them automatically if you specify the appropriate source and version in a module call block. Also, members of your organization might produce modules specifically crafted for your own infrastructure needs. [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software) include a private module registry for sharing modules internally within your organization. Using Modules[​](https://opentofu.org/docs/v1.10/language/modules/#using-modules "Direct link to Using Modules") ----------------------------------------------------------------------------------------------------------------- * [Module Blocks](https://opentofu.org/docs/v1.10/language/modules/syntax/) documents the syntax for calling a child module from a parent module, including meta-arguments like `for_each`. * [Module Sources](https://opentofu.org/docs/v1.10/language/modules/sources/) documents what kinds of paths, addresses, and URIs can be used in the `source` argument of a module block. * The Meta-Arguments section documents special arguments that can be used with every module, including [`providers`](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/) , [`depends_on`](https://opentofu.org/docs/v1.10/language/meta-arguments/depends_on/) , [`count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) , and [`for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) . Developing Modules[​](https://opentofu.org/docs/v1.10/language/modules/#developing-modules "Direct link to Developing Modules") -------------------------------------------------------------------------------------------------------------------------------- For information about developing reusable modules, see [Module Development](https://opentofu.org/docs/v1.10/language/modules/develop/) . * [The Root Module](https://opentofu.org/docs/v1.10/language/modules/#the-root-module) * [Child Modules](https://opentofu.org/docs/v1.10/language/modules/#child-modules) * [Published Modules](https://opentofu.org/docs/v1.10/language/modules/#published-modules) * [Using Modules](https://opentofu.org/docs/v1.10/language/modules/#using-modules) * [Developing Modules](https://opentofu.org/docs/v1.10/language/modules/#developing-modules) --- # Import | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/import/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Import ====== Experimental While we do not expect to make backwards-incompatible changes to syntax, the `-generate-config-out` flag and how OpenTofu processes imports during the plan stage and generates configuration may change in future releases. Use the `import` block to import existing infrastructure resources into OpenTofu, bringing them under OpenTofu's management. Unlike the `tofu import` command, configuration-driven import using `import` blocks is predictable, works with CICD pipelines, and lets you preview an import operation before modifying state. Once imported, OpenTofu tracks the resource in your state file. You can then manage the imported resource like any other, updating its attributes and destroying it as part of a standard resource lifecycle. The `import` block records that OpenTofu imported the resource and did not create it. After importing, you can optionally remove import blocks from your configuration or leave them as a record of the resource's origin. Syntax[​](https://opentofu.org/docs/v1.10/language/import/#syntax "Direct link to Syntax") ------------------------------------------------------------------------------------------- You can add an `import` block to any OpenTofu configuration file. A common pattern is to create an `imports.tf` file, or to place each `import` block beside the `resource` block it imports into. Code Block import { to = aws_instance.example id = "i-abcd1234"}resource "aws_instance" "example" { name = "hashi" # (other resource arguments...)} The above `import` block defines an import of the AWS instance with the ID "i-abcd1234" into the `aws_instance.example` resource in the root module. The `import` block has the following arguments: * `to` - The instance address this resource will have in your state file. * `id` - A string with the [import ID](https://opentofu.org/docs/v1.10/language/import/#import-id) of the resource. * `provider` (optional) - An optional custom resource provider, see [The Resource provider Meta-Argument](https://opentofu.org/docs/v1.10/language/meta-arguments/resource-provider/) for details. * `for_each` (optional) - Import several resources by iterating over a map or a set. See [Importing multiple resources](https://opentofu.org/docs/v1.10/language/import/#importing-multiple-resources) below. If you do not set the `provider` argument, OpenTofu attempts to import from the default provider. ### Import ID[​](https://opentofu.org/docs/v1.10/language/import/#import-id "Direct link to Import ID") The import block requires you to provide the `id` argument with a literal string of your resource's import ID. OpenTofu needs this import ID to locate the resource you want to import. The identifier you use for a resource's import ID is resource-specific. You can find the required ID in the provider's documentation for the resource you wish to import. Plan and apply an import[​](https://opentofu.org/docs/v1.10/language/import/#plan-and-apply-an-import "Direct link to Plan and apply an import") ------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu processes the `import` block during the plan stage. Once a plan is approved, OpenTofu imports the resource into its state during the subsequent apply stage. To import a resource using `import` blocks, you must: 1. Define an `import` block for the resource(s). 2. Add a corresponding `resource` block to your configuration , or [generate configuration](https://opentofu.org/docs/v1.10/language/import/generating-configuration/) for that resource. 3. Run `tofu plan` to review how OpenTofu will import the resource(s). 4. Apply the configuration to import the resources and update your OpenTofu state. The `import` block is [_idempotent_](https://en.wikipedia.org/wiki/Idempotence) , meaning that applying an import action and running another plan will not generate another import action as long as that resource remains in your state. OpenTofu only needs to import a given resource once. Attempting to import a resource into the same address again is a harmless no-op. You can remove `import` blocks after completing the import or safely leave them in your configuration as a record of the resource's origin for future module maintainers. For more information on maintaining configurations over time, see [Refactoring](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/) . Resource configuration[​](https://opentofu.org/docs/v1.10/language/import/#resource-configuration "Direct link to Resource configuration") ------------------------------------------------------------------------------------------------------------------------------------------- Before importing, you must add configuration for every resource you want OpenTofu to import. Otherwise, OpenTofu throws an error during planning, insisting you add resource configuration before it can successfully import. You can create resource configuration manually or [generate it using OpenTofu](https://opentofu.org/docs/v1.10/language/import/generating-configuration/) . We recommend writing a `resource` block if you know what most of the [resource's arguments](https://opentofu.org/docs/v1.10/language/resources/syntax/#resource-arguments) will be. For example, your configuration may already contain a similar resource whose configuration you can copy and modify. We recommend [generating configuration](https://opentofu.org/docs/v1.10/language/import/generating-configuration/) when importing multiple resources or a single complex resource that you do not already have the configuration for. ### Add a `resource` block[​](https://opentofu.org/docs/v1.10/language/import/#add-a-resource-block "Direct link to add-a-resource-block") Add a `resource` block for the resource to import. The resource address must match the import block's `to` argument. Code Block import { to = aws_instance.example id = "i-abcd1234"}resource "aws_instance" "example" { name = "renderer"} ### Generate configuration[​](https://opentofu.org/docs/v1.10/language/import/#generate-configuration "Direct link to Generate configuration") OpenTofu can generate HCL for resources that do not already exist in configuration. For more details, see [Generating Configuration](https://opentofu.org/docs/v1.10/language/import/generating-configuration/) . Examples[​](https://opentofu.org/docs/v1.10/language/import/#examples "Direct link to Examples") ------------------------------------------------------------------------------------------------- The following example demonstrates how to import into a module. Code Block import { to = module.instances.aws_instance.example id = "i-abcd1234"} The below example shows how to import a resource that includes [`count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) . Code Block import { to = aws_instance.example[0] id = "i-abcd1234"} The below example shows how to import a resource that includes [`for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) . Code Block import { to = aws_instance.example["foo"] id = "i-abcd1234"} Finally, the below example demonstrates how to import from a custom resource provider. Code Block provider "aws" { alias = "europe" region = "eu-west-1"}import { provider = aws.europe to = aws_instance.example["foo"] id = "i-abcd1234"} ### Importing multiple resources[​](https://opentofu.org/docs/v1.10/language/import/#importing-multiple-resources "Direct link to Importing multiple resources") You can import multiple resources with one import block by using a `for_each` expression. This expression accepts [a set, a tuple or a map](https://opentofu.org/docs/v1.10/language/expressions/types/) and provides the `each.key` and `each.value` variables to access the individual elements. In the example below, you can specify a list of server IDs to be imported. If you specify an empty list, the `random_id` resource will generate all IDs randomly. If you specify some IDs, the import block will import the specified IDs and the resource will randomly generate the rest. Note, the `random_id` resource requires the IDs to be in base64 format. Code Block variable "server_ids" { type = list(string)}resource "random_id" "test_id" { byte_length = 8 count = 2}import { to = random_id.test_id[tonumber(each.key)] id = each.value for_each = { for idx, item in var.server_ids: idx => item }}output "id" { value = random_id.test_id.*.b64_url} Note [Generating configuration](https://opentofu.org/docs/v1.10/language/import/generating-configuration/) is currently not possible when using `for_each` on `import` blocks. * [Syntax](https://opentofu.org/docs/v1.10/language/import/#syntax) * [Import ID](https://opentofu.org/docs/v1.10/language/import/#import-id) * [Plan and apply an import](https://opentofu.org/docs/v1.10/language/import/#plan-and-apply-an-import) * [Resource configuration](https://opentofu.org/docs/v1.10/language/import/#resource-configuration) * [Add a `resource` block](https://opentofu.org/docs/v1.10/language/import/#add-a-resource-block) * [Generate configuration](https://opentofu.org/docs/v1.10/language/import/#generate-configuration) * [Examples](https://opentofu.org/docs/v1.10/language/import/#examples) * [Importing multiple resources](https://opentofu.org/docs/v1.10/language/import/#importing-multiple-resources) --- # Standard Module Structure | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/modules/develop/structure/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Standard Module Structure ========================= The standard module structure is a file and directory layout we recommend for reusable modules distributed in separate repositories. OpenTofu tooling is built to understand the standard module structure and use that structure to generate documentation, index modules for the module registry, and more. The standard module structure expects the layout documented below. The list may appear long, but everything is optional except for the root module. Most modules don't need to do any extra work to follow the standard structure. * **Root module**. This is the **only required element** for the standard module structure. OpenTofu files must exist in the root directory of the repository. This should be the primary entrypoint for the module and is expected to be opinionated. For the [Consul module](https://github.com/hashicorp/terraform-aws-consul) the root module sets up a complete Consul cluster. It makes a lot of assumptions however, and we expect that advanced users will use specific _nested modules_ to more carefully control what they want. * **README**. The root module and any nested modules should have README files. This file should be named `README` or `README.md`. The latter will be treated as markdown. There should be a description of the module and what it should be used for. If you want to include an example for how this module can be used in combination with other resources, put it in an [examples directory like this](https://github.com/hashicorp/terraform-aws-consul/tree/master/examples) . Consider including a visual diagram depicting the infrastructure resources the module may create and their relationship. The README doesn't need to document inputs or outputs of the module because tooling will automatically generate this. If you are linking to a file or embedding an image contained in the repository itself, use a commit-specific absolute URL so the link won't point to the wrong version of a resource in the future. * **LICENSE**. The license under which this module is available. If you are publishing a module publicly, many organizations will not adopt a module unless a clear license is present. We recommend always having a license file, even if it is not an open source license. * **`main.tf`, `variables.tf`, `outputs.tf`**. These are the recommended filenames for a minimal module, even if they're empty. `main.tf` should be the primary entrypoint. For a simple module, this may be where all the resources are created. For a complex module, resource creation may be split into multiple files but any nested module calls should be in the main file. `variables.tf` and `outputs.tf` should contain the declarations for variables and outputs, respectively. * **Variables and outputs should have descriptions.** All variables and outputs should have one or two sentence descriptions that explain their purpose. This is used for documentation. See the documentation for [variable configuration](https://opentofu.org/docs/v1.10/language/values/variables/) and [output configuration](https://opentofu.org/docs/v1.10/language/values/outputs/) for more details. * **Nested modules**. Nested modules should exist under the `modules/` subdirectory. Any nested module with a `README.md` is considered usable by an external user. If a README doesn't exist, it is considered for internal use only. These are purely advisory; OpenTofu will not actively deny usage of internal modules. Nested modules should be used to split complex behavior into multiple small modules that advanced users can carefully pick and choose. For example, the [Consul module](https://github.com/hashicorp/terraform-aws-consul) has a nested module for creating the Cluster that is separate from the module to setup necessary IAM policies. This allows a user to bring in their own IAM policy choices. If the root module includes calls to nested modules, they should use relative paths like `./modules/consul-cluster` so that OpenTofu will consider them to be part of the same repository or package, rather than downloading them again separately. If a repository or package contains multiple nested modules, they should ideally be [composable](https://opentofu.org/docs/v1.10/language/modules/develop/composition/) by the caller, rather than calling directly to each other and creating a deeply-nested tree of modules. * **Examples**. Examples of using the module should exist under the `examples/` subdirectory at the root of the repository. Each example may have a README to explain the goal and usage of the example. Examples for submodules should also be placed in the root `examples/` directory. Because examples will often be copied into other repositories for customization, any `module` blocks should have their `source` set to the address an external caller would use, not to a relative path. A minimal recommended module following the standard structure is shown below. While the root module is the only required element, we recommend the structure below as the minimum: Code Block $ tree minimal-module/.β”œβ”€β”€ README.mdβ”œβ”€β”€ main.tfβ”œβ”€β”€ variables.tfβ”œβ”€β”€ outputs.tf A complete example of a module following the standard structure is shown below. This example includes all optional elements and is therefore the most complex a module can become: Code Block $ tree complete-module/.β”œβ”€β”€ README.mdβ”œβ”€β”€ main.tfβ”œβ”€β”€ variables.tfβ”œβ”€β”€ outputs.tfβ”œβ”€β”€ ...β”œβ”€β”€ modules/β”‚Β Β  β”œβ”€β”€ nestedA/β”‚Β Β  β”‚Β Β  β”œβ”€β”€ README.mdβ”‚Β Β  β”‚Β Β  β”œβ”€β”€ variables.tfβ”‚Β Β  β”‚Β Β  β”œβ”€β”€ main.tfβ”‚Β Β  β”‚Β Β  β”œβ”€β”€ outputs.tfβ”‚Β Β  β”œβ”€β”€ nestedB/β”‚Β Β  β”œβ”€β”€ .../β”œβ”€β”€ examples/β”‚Β Β  β”œβ”€β”€ exampleA/β”‚Β Β  β”‚Β Β  β”œβ”€β”€ main.tfβ”‚Β Β  β”œβ”€β”€ exampleB/β”‚Β Β  β”œβ”€β”€ .../ --- # Resource Behavior | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/resources/behavior/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Resource Behavior ================= A `resource` block declares that you want a particular infrastructure object to exist with the given settings. If you are writing a new configuration for the first time, the resources it defines will exist _only_ in the configuration, and will not yet represent real infrastructure objects in the target platform. _Applying_ an OpenTofu configuration is the process of creating, updating, and destroying real infrastructure objects in order to make their settings match the configuration. How OpenTofu Applies a Configuration[​](https://opentofu.org/docs/v1.10/language/resources/behavior/#how-opentofu-applies-a-configuration "Direct link to How OpenTofu Applies a Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When OpenTofu creates a new infrastructure object represented by a `resource` block, the identifier for that real object is saved in OpenTofu's [state](https://opentofu.org/docs/v1.10/language/state/) , allowing it to be updated and destroyed in response to future changes. For resource blocks that already have an associated infrastructure object in the state, OpenTofu compares the actual configuration of the object with the arguments given in the configuration and, if necessary, updates the object to match the configuration. In summary, applying an OpenTofu configuration will: * _Create_ resources that exist in the configuration but are not associated with a real infrastructure object in the state. * _Destroy_ resources that exist in the state but no longer exist in the configuration. * _Forget_ resources that exist in the state but no longer in the configuration and are referenced in a `removed` block within the configuration. * _Update in-place_ resources whose arguments have changed. * _Destroy and re-create_ resources whose arguments have changed but which cannot be updated in-place due to remote API limitations. This general behavior applies for all resources, regardless of type. The details of what it means to create, update, or destroy a resource are different for each resource type, but this standard set of verbs is common across them all. The meta-arguments within `resource` blocks, documented in the sections below, allow some details of this standard resource behavior to be customized on a per-resource basis. Accessing Resource Attributes[​](https://opentofu.org/docs/v1.10/language/resources/behavior/#accessing-resource-attributes "Direct link to Accessing Resource Attributes") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [Expressions](https://opentofu.org/docs/v1.10/language/expressions/) within an OpenTofu module can access information about resources in the same module, and you can use that information to help configure other resources. Use the `..` syntax to reference a resource attribute in an expression. In addition to arguments specified in the configuration, resources often provide read-only attributes with information obtained from the remote API; this often includes things that can't be known until the resource is created, like the resource's unique random ID. Many providers also include [data sources](https://opentofu.org/docs/v1.10/language/data-sources/) , which are a special type of resource used only for looking up information. For a list of the attributes a resource or data source type provides, consult its documentation; these are generally included in a second list below its list of configurable arguments. For more information about referencing resource attributes in expressions, see [Expressions: References to Resource Attributes](https://opentofu.org/docs/v1.10/language/expressions/references/#references-to-resource-attributes) . Resource Dependencies[​](https://opentofu.org/docs/v1.10/language/resources/behavior/#resource-dependencies "Direct link to Resource Dependencies") ---------------------------------------------------------------------------------------------------------------------------------------------------- Most resources in a configuration don't have any particular relationship, and OpenTofu can make changes to several unrelated resources in parallel. However, some resources must be processed after other specific resources; sometimes this is because of how the resource works, and sometimes the resource's configuration just requires information generated by another resource. Most resource dependencies are handled automatically. OpenTofu analyses any [expressions](https://opentofu.org/docs/v1.10/language/expressions/) within a `resource` block to find references to other objects, and treats those references as implicit ordering requirements when creating, updating, or destroying resources. Since most resources with behavioral dependencies on other resources also refer to those resources' data, it's usually not necessary to manually specify dependencies between resources. However, some dependencies cannot be recognized implicitly in configuration. For example, if OpenTofu must manage access control policies _and_ take actions that require those policies to be present, there is a hidden dependency between the access policy and a resource whose creation depends on it. In these rare cases, [the `depends_on` meta-argument](https://opentofu.org/docs/v1.10/language/meta-arguments/depends_on/) can explicitly specify a dependency. You can also use the [`replace_triggered_by` meta-argument](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/#replace_triggered_by) to add dependencies between otherwise independent resources. It forces OpenTofu to replace the parent resource when there is a change to a referenced resource or resource attribute. Local-only Resources[​](https://opentofu.org/docs/v1.10/language/resources/behavior/#local-only-resources "Direct link to Local-only Resources") ------------------------------------------------------------------------------------------------------------------------------------------------- While most resource types correspond to an infrastructure object type that is managed via a remote network API, there are certain specialized resource types that operate only within OpenTofu itself, calculating some results and saving those results in the state for future use. For example, local-only resource types exist for [generating private keys](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) , [issuing self-signed TLS certificates](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/self_signed_cert) , and even [generating random ids](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) . While these resource types often have a more marginal purpose than those managing "real" infrastructure objects, they can be useful as glue to help connect together other resources. The behavior of local-only resources is the same as all other resources, but their result data exists only within the OpenTofu state. "Destroying" such a resource means only to remove it from the state, discarding its data. * [How OpenTofu Applies a Configuration](https://opentofu.org/docs/v1.10/language/resources/behavior/#how-opentofu-applies-a-configuration) * [Accessing Resource Attributes](https://opentofu.org/docs/v1.10/language/resources/behavior/#accessing-resource-attributes) * [Resource Dependencies](https://opentofu.org/docs/v1.10/language/resources/behavior/#resource-dependencies) * [Local-only Resources](https://opentofu.org/docs/v1.10/language/resources/behavior/#local-only-resources) --- # remote-exec Provisioner | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/resources/provisioners/remote-exec/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page remote-exec Provisioner ======================= The `remote-exec` provisioner invokes a script on a remote resource after it is created. This can be used to run a configuration management tool, bootstrap into a cluster, etc. To invoke a local process, see the `local-exec` [provisioner](https://opentofu.org/docs/v1.10/language/resources/provisioners/local-exec/) instead. The `remote-exec` provisioner requires a [connection](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/) and supports both `ssh` and `winrm`. Important Use provisioners as a last resort. There are better alternatives for most situations. Refer to [Declaring Provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/) for more details. Example usage[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/remote-exec/#example-usage "Direct link to Example usage") -------------------------------------------------------------------------------------------------------------------------------------------- Code Block resource "aws_instance" "web" { # ... # Establishes connection to be used by all # generic remote provisioners (i.e. file/remote-exec) connection { type = "ssh" user = "root" password = var.root_password host = self.public_ip } provisioner "remote-exec" { inline = [ "puppet apply", "consul join ${aws_instance.web.private_ip}", ] }} Argument Reference[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/remote-exec/#argument-reference "Direct link to Argument Reference") ----------------------------------------------------------------------------------------------------------------------------------------------------------- The following arguments are supported: * `inline` - This is a list of command strings. The provisioner uses a default shell unless you specify a shell as the first command (eg., `#!/bin/bash`). You cannot provide this with `script` or `scripts`. * `script` - This is a path (relative or absolute) to a local script that will be copied to the remote resource and then executed. This cannot be provided with `inline` or `scripts`. * `scripts` - This is a list of paths (relative or absolute) to local scripts that will be copied to the remote resource and then executed. They are executed in the order they are provided. This cannot be provided with `inline` or `script`. Note Since `inline` is implemented by concatenating commands into a script, [`on_failure`](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#failure-behavior) applies only to the final command in the list. In particular, with `on_failure = fail` (the default behaviour) earlier commands will be allowed to fail, and later commands will also execute. If this behaviour is not desired, consider using `"set -o errexit"` as the first command. Script Arguments[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/remote-exec/#script-arguments "Direct link to Script Arguments") ----------------------------------------------------------------------------------------------------------------------------------------------------- You cannot pass any arguments to scripts using the `script` or `scripts` arguments to this provisioner. If you want to specify arguments, upload the script with the [file provisioner](https://opentofu.org/docs/v1.10/language/resources/provisioners/file/) and then use `inline` to call it. Example: Code Block resource "aws_instance" "web" { # ... provisioner "file" { source = "script.sh" destination = "/tmp/script.sh" } provisioner "remote-exec" { inline = [ "chmod +x /tmp/script.sh", "/tmp/script.sh args", ] }} * [Example usage](https://opentofu.org/docs/v1.10/language/resources/provisioners/remote-exec/#example-usage) * [Argument Reference](https://opentofu.org/docs/v1.10/language/resources/provisioners/remote-exec/#argument-reference) * [Script Arguments](https://opentofu.org/docs/v1.10/language/resources/provisioners/remote-exec/#script-arguments) --- # local-exec Provisioner | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/resources/provisioners/local-exec/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page local-exec Provisioner ====================== The `local-exec` provisioner invokes a local executable after a resource is created. This invokes a process on the machine running OpenTofu, not on the resource. See the `remote-exec` [provisioner](https://opentofu.org/docs/v1.10/language/resources/provisioners/remote-exec/) to run commands on the resource. Note that even though the resource will be fully created when the provisioner is run, there is no guarantee that it will be in an operable state - for example system services such as `sshd` may not be started yet on compute resources. Important Use provisioners as a last resort. There are better alternatives for most situations. Refer to [Declaring Provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/) for more details. Example usage[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/local-exec/#example-usage "Direct link to Example usage") ------------------------------------------------------------------------------------------------------------------------------------------- Code Block resource "aws_instance" "web" { # ... provisioner "local-exec" { command = "echo ${self.private_ip} >> private_ips.txt" }} Argument Reference[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/local-exec/#argument-reference "Direct link to Argument Reference") ---------------------------------------------------------------------------------------------------------------------------------------------------------- The following arguments are supported: * `command` - (Required) This is the command to execute. It can be provided as a relative path to the current working directory or as an absolute path. It is evaluated in a shell, and can use environment variables or OpenTofu variables. * `working_dir` - (Optional) If provided, specifies the working directory where `command` will be executed. It can be provided as a relative path to the current working directory or as an absolute path. The directory must exist. * `interpreter` - (Optional) If provided, this is a list of interpreter arguments used to execute the command. The first argument is the interpreter itself. It can be provided as a relative path to the current working directory or as an absolute path. The remaining arguments are appended prior to the command. This allows building command lines of the form "/bin/bash", "-c", "echo foo". If `interpreter` is unspecified, sensible defaults will be chosen based on the system OS. * `environment` - (Optional) block of key value pairs representing the environment of the executed command. inherits the current process environment. * `when` - (Optional) If provided, specifies when OpenTofu will execute the command. For example, `when = destroy` specifies that the provisioner will run when the associated resource is destroyed. Refer to [Destroy-Time Provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#destroy-time-provisioners) for details. * `quiet` - (Optional) If set to `true`, OpenTofu will not print the command to be executed to stdout, and will instead print "Suppressed by quiet=true". Note that the output of the command will still be printed in any case. ### Interpreter Examples[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/local-exec/#interpreter-examples "Direct link to Interpreter Examples") Code Block resource "terraform_data" "example1" { provisioner "local-exec" { command = "open WFH, '>completed.txt' and print WFH scalar localtime" interpreter = ["perl", "-e"] }} Code Block resource "terraform_data" "example2" { provisioner "local-exec" { command = "Get-Date > completed.txt" interpreter = ["PowerShell", "-Command"] }} Code Block resource "aws_instance" "web" { # ... provisioner "local-exec" { command = "echo $FOO $BAR $BAZ >> env_vars.txt" environment = { FOO = "bar" BAR = 1 BAZ = "true" } }} * [Example usage](https://opentofu.org/docs/v1.10/language/resources/provisioners/local-exec/#example-usage) * [Argument Reference](https://opentofu.org/docs/v1.10/language/resources/provisioners/local-exec/#argument-reference) * [Interpreter Examples](https://opentofu.org/docs/v1.10/language/resources/provisioners/local-exec/#interpreter-examples) --- # File Provisioner | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/resources/provisioners/file/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page File Provisioner ================ The `file` provisioner copies files or directories from the machine running OpenTofu to the newly created resource. The `file` provisioner supports both `ssh` and `winrm` type [connections](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/) . Important Use provisioners as a last resort. There are better alternatives for most situations. Refer to [Declaring Provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/) for more details. Example usage[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/file/#example-usage "Direct link to Example usage") ------------------------------------------------------------------------------------------------------------------------------------- Code Block resource "aws_instance" "web" { # ... # Copies the myapp.conf file to /etc/myapp.conf provisioner "file" { source = "conf/myapp.conf" destination = "/etc/myapp.conf" } # Copies the string in content into /tmp/file.log provisioner "file" { content = "ami used: ${self.ami}" destination = "/tmp/file.log" } # Copies the configs.d folder to /etc/configs.d provisioner "file" { source = "conf/configs.d" destination = "/etc" } # Copies all files and folders in apps/app1 to D:/IIS/webapp1 provisioner "file" { source = "apps/app1/" destination = "D:/IIS/webapp1" }} Note When the `file` provisioner communicates with a Windows system over SSH, you must configure OpenSSH to run the commands with `cmd.exe` and not PowerShell. PowerShell causes file parsing errors because it is incompatible with both Unix shells and the Windows command interpreter. Argument Reference[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/file/#argument-reference "Direct link to Argument Reference") ---------------------------------------------------------------------------------------------------------------------------------------------------- The following arguments are supported: * `source` - The source file or directory. Specify it either relative to the current working directory or as an absolute path. This argument cannot be combined with `content`. * `content` - The direct content to copy on the destination. If destination is a file, the content will be written on that file. In case of a directory, a file named `tf-file-content` is created inside that directory. We recommend using a file as the destination when using `content`. This argument cannot be combined with `source`. * `destination` - (Required) The destination path to write to on the remote system. See [Destination Paths](https://opentofu.org/docs/v1.10/language/resources/provisioners/file/#destination-paths) below for more information. Destination Paths[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/file/#destination-paths "Direct link to Destination Paths") ------------------------------------------------------------------------------------------------------------------------------------------------- The path you provide in the `destination` argument will be evaluated by the remote system, rather than by OpenTofu itself. Therefore the valid values for that argument can vary depending on the operating system and remote access software running on the target. When connecting over SSH, the `file` provisioner passes the given destination path verbatim to the `scp` program on the remote host. By default, OpenSSH's `scp` implementation runs in the remote user's home directory and so you can specify a relative path to upload into that home directory, or an absolute path to upload to some other location. The remote `scp` process will run with the access level of the user specified in the `connection` block, and so permissions may prevent writing directly to locations outside of the home directory. Because WinRM has no corresponding file transfer protocol, for WinRM connections the `file` provisioner uses a more complex process: 1. Generate a temporary filename in the directory given in the remote system's `TEMP` environment variable, using a pseudorandom UUID for uniqueness. 2. Use sequential generated `echo` commands over WinRM to gradually append base64-encoded chunks of the source file to the chosen temporary file. 3. Use an uploaded PowerShell script to read the temporary file, base64-decode, and write the raw result into the destination file. In the WinRM case, the destination path is therefore interpreted by PowerShell and so you must take care not to use any meta-characters that PowerShell might interpret. In particular, avoid including any untrusted external input in your `destination` argument when using WinRM, because it can serve as a vector for arbitrary PowerShell code execution on the remote system. Modern Windows systems support running an OpenSSH server, so we strongly recommend choosing SSH over WinRM wherever possible, and using WinRM only as a last resort when working with obsolete Windows versions. Directory Uploads[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/file/#directory-uploads "Direct link to Directory Uploads") ------------------------------------------------------------------------------------------------------------------------------------------------- The `file` provisioner can upload a complete directory to the remote machine. When uploading a directory, there are some additional considerations. When using the `ssh` connection type the destination directory must already exist. If you need to create it, use a remote-exec provisioner just prior to the file provisioner in order to create the directory When using the `winrm` connection type the destination directory will be created for you if it doesn't already exist. The existence of a trailing slash on the source path will determine whether the directory name will be embedded within the destination, or whether the destination will be created. For example: * If the source is `/foo` (no trailing slash), and the destination is `/tmp`, then the contents of `/foo` on the local machine will be uploaded to `/tmp/foo` on the remote machine. The `foo` directory on the remote machine will be created by OpenTofu. * If the source, however, is `/foo/` (a trailing slash is present), and the destination is `/tmp`, then the contents of `/foo` will be uploaded directly into `/tmp`. * [Example usage](https://opentofu.org/docs/v1.10/language/resources/provisioners/file/#example-usage) * [Argument Reference](https://opentofu.org/docs/v1.10/language/resources/provisioners/file/#argument-reference) * [Destination Paths](https://opentofu.org/docs/v1.10/language/resources/provisioners/file/#destination-paths) * [Directory Uploads](https://opentofu.org/docs/v1.10/language/resources/provisioners/file/#directory-uploads) --- # Using the Cloud Backend with OpenTofu CLI | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/cloud/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Using the Cloud Backend with OpenTofu CLI ========================================= The OpenTofu CLI lets you use cloud backends on the command line. When you use the cloud backend CLI workflow, operations like `tofu plan` or `tofu apply` are remotely executed in the cloud backend's run environment by default, with log output streaming to the local terminal. This lets you use cloud backend's features within the familiar OpenTofu CLI workflow. Cloud backend services may choose to implement only a subset of the available features. Workspaces can also be configured for local execution, in which case the cloud backend only stores state. In this mode, the cloud backend behaves just like a standard state backend. Documentation Summary[​](https://opentofu.org/docs/v1.11/cli/cloud/#documentation-summary "Direct link to Documentation Summary") ---------------------------------------------------------------------------------------------------------------------------------- * [Cloud Backend Settings](https://opentofu.org/docs/v1.11/cli/cloud/settings/) documents the `cloud` block that you must add to your configuration to enable cloud backend support. * [Initializing and Migrating](https://opentofu.org/docs/v1.11/cli/cloud/migrating/) describes how to start using the cloud backend with a working directory that already has state data. * [Command Line Arguments](https://opentofu.org/docs/v1.11/cli/cloud/command-line-arguments/) lists the OpenTofu command flags that are specific to using OpenTofu with the cloud backend. * [Documentation Summary](https://opentofu.org/docs/v1.11/cli/cloud/#documentation-summary) --- # Command Line Arguments | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/cloud/command-line-arguments/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Command Line Arguments ====================== When your configuration includes a `cloud` block, commands that make local modifications to OpenTofu state and then push them back up to the remote workspace accept the following option to modify that behavior: * `-ignore-remote-version` - Override checking that the local and remote OpenTofu versions agree, making an operation proceed even when there is a mismatch. State-modification operations usually require using a local version of the OpenTofu CLI that is compatible with the OpenTofu version selected in the remote workspace settings. This prevents the local operation from creating a new state snapshot that the workspace's remote execution environment cannot decode. We recommend against using this option unless absolutely necessary. Overriding this check can result in a cloud backend workspace that is no longer able to complete remote operations with the currently selected version of OpenTofu. --- # CLI Authentication | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/auth/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) CLI Authentication ================== [TACOS](https://opentofu.org/docs/v1.11/intro/tacos/) (TF Automation and Collaboration Software) are platforms that perform as part of their offering OpenTofu runs to provision infrastructure, offering a collaboration-focused environment that makes it easier for teams to use OpenTofu together. OpenTofu CLI integrates with [TACOS](https://opentofu.org/docs/v1.11/intro/tacos/) in several ways β€”Β it can be a front-end for CLI-driven runs, and can also use some [TACOS](https://opentofu.org/docs/v1.11/intro/tacos/) as a state backend, a private module registry, or a private provider registry. All of these integrations require you to authenticate OpenTofu CLI with your [TACOS](https://opentofu.org/docs/v1.11/intro/tacos/) account. The best way to handle CLI authentication is with the `login` and `logout` commands, which help automate the process of getting an API token for your [TACOS](https://opentofu.org/docs/v1.11/intro/tacos/) user account. For details, see: * [The `tofu login` command](https://opentofu.org/docs/v1.11/cli/commands/login/) * [The `tofu logout` command](https://opentofu.org/docs/v1.11/cli/commands/logout/) --- # Backend Type: consul | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/backends/consul/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Backend Type: consul ==================== Stores the state in the [Consul](https://www.consul.io/) KV store at a given path. This backend supports [state locking](https://opentofu.org/docs/v1.10/language/state/locking/) . Example Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/consul/#example-configuration "Direct link to Example Configuration") ---------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block terraform { backend "consul" { address = "consul.example.com" scheme = "https" path = "full/path" }} Note that for the access credentials we recommend using a [partial configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#partial-configuration) . Data Source Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/consul/#data-source-configuration "Direct link to Data Source Configuration") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block data "terraform_remote_state" "foo" { backend = "consul" config = { path = "full/path" }} Configuration Variables[​](https://opentofu.org/docs/v1.10/language/settings/backends/consul/#configuration-variables "Direct link to Configuration Variables") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Warning We recommend using environment variables to supply credentials and other sensitive data. If you use `-backend-config` or hardcode these values directly in your configuration, OpenTofu will include these values in both the `.terraform` subdirectory and in plan files. Refer to [Credentials and Sensitive Data](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#credentials-and-sensitive-data) for details. The following configuration options / environment variables are supported: * `path` - (Required) Path in the Consul KV store * `access_token` / `CONSUL_HTTP_TOKEN` - (Required) Access token * `address` / `CONSUL_HTTP_ADDR` - (Optional) DNS name and port of your Consul endpoint specified in the format `dnsname:port`. Defaults to the local agent HTTP listener. * `scheme` - (Optional) Specifies what protocol to use when talking to the given `address`, either `http` or `https`. SSL support can also be triggered by setting then environment variable `CONSUL_HTTP_SSL` to `true`. * `datacenter` - (Optional) The datacenter to use. Defaults to that of the agent. * `http_auth` / `CONSUL_HTTP_AUTH` - (Optional) HTTP Basic Authentication credentials to be used when communicating with Consul, in the format of either `user` or `user:pass`. * `gzip` - (Optional) `true` to compress the state data using gzip, or `false` (the default) to leave it uncompressed. * `lock` - (Optional) `false` to disable locking. This defaults to true, but will require session permissions with Consul and at least kv write permissions on `$path/.lock` to perform locking. * `ca_file` / `CONSUL_CACERT` - (Optional) A path to a PEM-encoded certificate authority used to verify the remote agent's certificate. * `cert_file` / `CONSUL_CLIENT_CERT` - (Optional) A path to a PEM-encoded certificate provided to the remote agent; requires use of `key_file`. * `key_file` / `CONSUL_CLIENT_KEY` - (Optional) A path to a PEM-encoded private key, required if `cert_file` is specified. * [Example Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/consul/#example-configuration) * [Data Source Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/consul/#data-source-configuration) * [Configuration Variables](https://opentofu.org/docs/v1.10/language/settings/backends/consul/#configuration-variables) --- # Backend Type: http | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/backends/http/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Backend Type: http ================== Stores the state using a simple [REST](https://en.wikipedia.org/wiki/Representational_state_transfer) client. State will be fetched via GET, updated via POST, and purged with DELETE. The method used for updating is configurable. This backend optionally supports [state locking](https://opentofu.org/docs/v1.10/language/state/locking/) . When locking support is enabled it will use LOCK and UNLOCK requests providing the lock info in the body. The endpoint should return a 423: Locked or 409: Conflict with the holding lock info when it's already taken, 200: OK for success. Any other status will be considered an error. The ID of the holding lock info will be added as a query parameter to state updates requests. Example Usage[​](https://opentofu.org/docs/v1.10/language/settings/backends/http/#example-usage "Direct link to Example Usage") -------------------------------------------------------------------------------------------------------------------------------- Code Block terraform { backend "http" { address = "http://myrest.api.com/foo" lock_address = "http://myrest.api.com/foo" unlock_address = "http://myrest.api.com/foo" }} Data Source Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/http/#data-source-configuration "Direct link to Data Source Configuration") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block data "terraform_remote_state" "foo" { backend = "http" config = { address = "http://my.rest.api.com" }} Configuration Variables[​](https://opentofu.org/docs/v1.10/language/settings/backends/http/#configuration-variables "Direct link to Configuration Variables") -------------------------------------------------------------------------------------------------------------------------------------------------------------- Warning We recommend using environment variables to supply credentials and other sensitive data. If you use `-backend-config` or hardcode these values directly in your configuration, OpenTofu will include these values in both the `.terraform` subdirectory and in plan files. Refer to [Credentials and Sensitive Data](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#credentials-and-sensitive-data) for details. The following configuration options / environment variables are supported: * `address` / `TF_HTTP_ADDRESS` - (Required) The address of the REST endpoint * `update_method` / `TF_HTTP_UPDATE_METHOD` - (Optional) HTTP method to use when updating state. Defaults to `POST`. * `lock_address` / `TF_HTTP_LOCK_ADDRESS` - (Optional) The address of the lock REST endpoint. Defaults to disabled. * `lock_method` / `TF_HTTP_LOCK_METHOD` - (Optional) The HTTP method to use when locking. Defaults to `LOCK`. * `unlock_address` / `TF_HTTP_UNLOCK_ADDRESS` - (Optional) The address of the unlock REST endpoint. Defaults to disabled. * `unlock_method` / `TF_HTTP_UNLOCK_METHOD` - (Optional) The HTTP method to use when unlocking. Defaults to `UNLOCK`. * `username` / `TF_HTTP_USERNAME` - (Optional) The username for HTTP basic authentication * `password` / `TF_HTTP_PASSWORD` - (Optional) The password for HTTP basic authentication * `headers` - (Optional) Map of additional headers to be included in the HTTP requests sent to the backend. Defaults to `[]`. * `skip_cert_verification` - (Optional) Whether to skip TLS verification. Defaults to `false`. * `retry_max` / `TF_HTTP_RETRY_MAX` – (Optional) The number of HTTP request retries. Defaults to `2`. * `retry_wait_min` / `TF_HTTP_RETRY_WAIT_MIN` – (Optional) The minimum time in seconds to wait between HTTP request attempts. Defaults to `1`. * `retry_wait_max` / `TF_HTTP_RETRY_WAIT_MAX` – (Optional) The maximum time in seconds to wait between HTTP request attempts. Defaults to `30`. For mTLS authentication, the following three options may be set: * `client_certificate_pem` / `TF_HTTP_CLIENT_CERTIFICATE_PEM` - (Optional) A PEM-encoded certificate used by the server to verify the client during mutual TLS (mTLS) authentication. * `client_private_key_pem` /`TF_HTTP_CLIENT_PRIVATE_KEY_PEM` - (Optional) A PEM-encoded private key, required if client\_certificate\_pem is specified. * `client_ca_certificate_pem` / `TF_HTTP_CLIENT_CA_CERTIFICATE_PEM` - (Optional) A PEM-encoded CA certificate chain used by the client to verify server certificates during TLS authentication. * [Example Usage](https://opentofu.org/docs/v1.10/language/settings/backends/http/#example-usage) * [Data Source Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/http/#data-source-configuration) * [Configuration Variables](https://opentofu.org/docs/v1.10/language/settings/backends/http/#configuration-variables) --- # Upgrading to OpenTofu v1.6 | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/upgrade-guides/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Upgrading to OpenTofu v1.6 ========================== OpenTofu v1.6 is the first release in the stable OpenTofu v1.0 series. OpenTofu v1.6 honors the [OpenTofu v1.0 Compatibility Promises](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/) , but there are some behavior changes outside of those promises that may affect a small number of users. Specifically, the following updates may require additional upgrade steps: * [Linux DNS resolver changes](https://opentofu.org/docs/v1.10/language/upgrade-guides/#linux-dns-resolver-changes) See [the full changelog](https://github.com/opentofu/opentofu/blob/v1.6/CHANGELOG.md) for more details. If you encounter any problems during upgrading which are not covered this guide, please start a new topic in [the OpenTofu community forum](https://github.com/opentofu/opentofu/discussions) to discuss it. Linux DNS resolver changes[​](https://opentofu.org/docs/v1.10/language/upgrade-guides/#linux-dns-resolver-changes "Direct link to Linux DNS resolver changes") --------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu on Linux uses a built-in DNS resolver rather than using the DNS resolver from the platform's C library, because this allows OpenTofu to run on systems with many different C libraries. In OpenTofu v1.6, the DNS resolver will now notice when you have set the `trust-ad` option in your `/etc/resolve.conf` file, and will respond by setting the "authentic data" option in outgoing DNS requests to better match the behavior of the GNU libc DNS resolver. OpenTofu does not pay any attention to the corresponding option in responses, but some DNSSEC-aware recursive resolvers return different responses when the request option isn't set. This should therefore avoid some potential situations where a DNS request from OpenTofu might get a different response than a similar request from other software on your system. We don't expect this behavior change to be significant for most OpenTofu users. Note that this change affects only DNS requests made by OpenTofu CLI itself, and not requests made by providers. Provider plugins are separate programs which handle DNS resolution themselves and so may have different behavior. * [Linux DNS resolver changes](https://opentofu.org/docs/v1.10/language/upgrade-guides/#linux-dns-resolver-changes) --- # The lifecycle Meta-Argument | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page The `lifecycle` Meta-Argument ============================= The [Resource Behavior](https://opentofu.org/docs/v1.10/language/resources/behavior/) page describes the general lifecycle for resources. Some details of that behavior can be customized using the special nested `lifecycle` block within a resource block body: Code Block resource "azurerm_resource_group" "example" { # ... lifecycle { create_before_destroy = true }} Syntax and Arguments[​](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/#syntax-and-arguments "Direct link to Syntax and Arguments") ------------------------------------------------------------------------------------------------------------------------------------------------------- `lifecycle` is a nested block that can appear within a resource block. The `lifecycle` block and its contents are meta-arguments, available for all `resource` blocks regardless of type. The arguments available within a `lifecycle` block are `create_before_destroy`, `prevent_destroy`, `ignore_changes`, and `replace_triggered_by`. * `create_before_destroy` (bool) - By default, when OpenTofu must change a resource argument that cannot be updated in-place due to remote API limitations, OpenTofu will instead destroy the existing object and then create a new replacement object with the new configured arguments. The `create_before_destroy` meta-argument changes this behavior so that the new replacement object is created _first,_ and the prior object is destroyed after the replacement is created. This is an opt-in behavior because many remote object types have unique name requirements or other constraints that must be accommodated for both a new and an old object to exist concurrently. Some resource types offer special options to append a random suffix onto each object name to avoid collisions, for example. OpenTofu CLI cannot automatically activate such features, so you must understand the constraints for each resource type before using `create_before_destroy` with it. Note that OpenTofu propagates and applies the `create_before_destroy` meta-attribute behaviour to all resource dependencies. For example, if `create_before_destroy` is enabled on resource A but not on resource B, but resource A is dependent on resource B, then OpenTofu enables `create_before_destroy` for resource B implicitly by default and stores it to the state file. You cannot override `create_before_destroy` to `false` on resource B because that would imply dependency cycles in the graph. Destroy provisioners of this resource do not run if `create_before_destroy` is set to `true`. This [GitHub issue](https://github.com/hashicorp/terraform/issues/13549) contains more details. * `prevent_destroy` (bool) - This meta-argument, when set to `true`, will cause OpenTofu to reject with an error any plan that would destroy the infrastructure object associated with the resource, as long as the argument remains present in the configuration. This can be used as a measure of safety against the accidental replacement of objects that may be costly to reproduce, such as database instances. However, it will make certain configuration changes impossible to apply, and will prevent the use of the `tofu destroy` command once such objects are created, and so this option should be used sparingly. Since this argument must be present in configuration for the protection to apply, note that this setting does not prevent the remote object from being destroyed if the `resource` block were removed from configuration entirely: in that case, the `prevent_destroy` setting is removed along with it, and so OpenTofu will allow the destroy operation to succeed. * `ignore_changes` (list of attribute names) - By default, OpenTofu detects any difference in the current settings of a real infrastructure object and plans to update the remote object to match configuration. The `ignore_changes` feature is intended to be used when a resource is created with references to data that may change in the future, but should not affect said resource after its creation. In some rare cases, settings of a remote object are modified by processes outside of OpenTofu, which OpenTofu would then attempt to "fix" on the next run. In order to make OpenTofu share management responsibilities of a single object with a separate process, the `ignore_changes` meta-argument specifies resource attributes that OpenTofu should ignore when planning updates to the associated remote object. The arguments corresponding to the given attribute names are considered when planning a _create_ operation, but are ignored when planning an _update_. The arguments are the relative address of the attributes in the resource. Map and list elements can be referenced using index notation, like `tags["Name"]` and `list[0]` respectively. Code Block resource "aws_instance" "example" { # ... lifecycle { ignore_changes = [ # Ignore changes to tags, e.g. because a management agent # updates these based on some ruleset managed elsewhere. tags, ] }} Instead of a list, the special keyword `all` may be used to instruct OpenTofu to ignore _all_ attributes, which means that OpenTofu can create and destroy the remote object but will never propose updates to it. Only attributes defined by the resource type can be ignored. `ignore_changes` cannot be applied to itself or to any other meta-arguments. * `replace_triggered_by` (list of resource or attribute references) - Replaces the resource when any of the referenced items change. Supply a list of expressions referencing managed resources, instances, or instance attributes. When used in a resource that uses `count` or `for_each`, you can use `count.index` or `each.key` in the expression to reference specific instances of other resources that are configured with the same count or collection. References trigger replacement in the following conditions: * If the reference is to a resource with multiple instances, a plan to update or replace any instance will trigger replacement. * If the reference is to a single resource instance, a plan to update or replace that instance will trigger replacement. * If the reference is to a single attribute of a resource instance, any change to the attribute value will trigger replacement. You can only reference managed resources in `replace_triggered_by` expressions. This lets you modify these expressions without forcing replacement. Code Block resource "aws_appautoscaling_target" "ecs_target" { # ... lifecycle { replace_triggered_by = [ # Replace `aws_appautoscaling_target` each time this instance of # the `aws_ecs_service` is replaced. aws_ecs_service.svc.id ] }} `replace_triggered_by` allows only resource addresses because the decision is based on the planned actions for all of the given resources. Plain values such as local values or input variables do not have planned actions of their own, but you can treat them with a resource-like lifecycle by using them with [the `terraform_data` resource type](https://opentofu.org/docs/v1.10/language/resources/tf-data/) . Custom Condition Checks[​](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/#custom-condition-checks "Direct link to Custom Condition Checks") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- You can add `precondition` and `postcondition` blocks with a `lifecycle` block to specify assumptions and guarantees about how resources and data sources operate. The following examples creates a precondition that checks whether the AMI is properly configured. Code Block resource "aws_instance" "example" { instance_type = "t2.micro" ami = "ami-abc123" lifecycle { # The AMI ID must refer to an AMI that contains an operating system # for the `x86_64` architecture. precondition { condition = data.aws_ami.example.architecture == "x86_64" error_message = "The selected AMI must be for the x86_64 architecture." } }} Custom conditions can help capture assumptions, helping future maintainers understand the configuration design and intent. They also return useful information about errors earlier and in context, helping consumers more easily diagnose issues in their configurations. Refer to [Custom Conditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#preconditions-and-postconditions) for more details. Literal Values Only[​](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/#literal-values-only "Direct link to Literal Values Only") ---------------------------------------------------------------------------------------------------------------------------------------------------- The `lifecycle` settings all affect how OpenTofu constructs and traverses the dependency graph. As a result, only literal values can be used because the processing happens too early for arbitrary expression evaluation. * [Syntax and Arguments](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/#syntax-and-arguments) * [Custom Condition Checks](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/#custom-condition-checks) * [Literal Values Only](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/#literal-values-only) --- # Cloud Configuration | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/tf-cloud/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Cloud Configuration =================== The main module of an OpenTofu configuration can integrate with a cloud backend to enable its [CLI-driven run workflow](https://opentofu.org/docs/v1.10/cli/cloud/) (if supported by your cloud backend). You only need to configure these settings when you want to use OpenTofu CLI to interact with a cloud backend. A cloud backend ignores them when interacting with OpenTofu through version control or the API. Usage Example[​](https://opentofu.org/docs/v1.10/language/settings/tf-cloud/#usage-example "Direct link to Usage Example") --------------------------------------------------------------------------------------------------------------------------- To configure the cloud CLI integration, add a nested `cloud` block within the `terraform` block. You cannot use the CLI integration and a state backend in the same configuration. Refer to [Using the Cloud Backend](https://opentofu.org/docs/v1.10/cli/cloud/) in the OpenTofu CLI documentation for full configuration details, migration instructions, and command line arguments. Code Block locals { org = "example_corp"}terraform { cloud { organization = local.org hostname = "app.example.io" workspaces { tags = ["app"] } }} Note Cloud fields may not contain any references to data in the state or provider defined functions. All values must be able to be resolved during `tofu init` before the state is available. * [Usage Example](https://opentofu.org/docs/v1.10/language/settings/tf-cloud/#usage-example) --- # Backend Type: local | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/backends/local/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Backend Type: local =================== **Kind: Enhanced** The local backend stores state on the local filesystem, locks that state using system APIs, and performs operations locally. Example Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/local/#example-configuration "Direct link to Example Configuration") --------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block terraform { backend "local" { path = "relative/path/to/terraform.tfstate" }} Data Source Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/local/#data-source-configuration "Direct link to Data Source Configuration") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block data "terraform_remote_state" "foo" { backend = "local" config = { path = "${path.module}/../../terraform.tfstate" }} Configuration variables[​](https://opentofu.org/docs/v1.10/language/settings/backends/local/#configuration-variables "Direct link to Configuration variables") --------------------------------------------------------------------------------------------------------------------------------------------------------------- The following configuration options are supported: * `path` - (Optional) The path to the `tfstate` file. This defaults to "terraform.tfstate" relative to the root module by default. * `workspace_dir` - (Optional) The path to non-default workspaces. Command Line Arguments[​](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments "Direct link to Command Line Arguments") ------------------------------------------------------------------------------------------------------------------------------------------------------------ Note This section describes legacy features that we've preserved for backward compatibility but that we no longer recommend. See below for more details. For configurations that include a `backend "local"` block or that default to the local backend by not specifying a backend at all, most commands that either read or write state snapshots from the backend accept the following additional arguments: * `-state=FILENAME` - overrides the state filename when _reading_ the prior state snapshot. * `-state-out=FILENAME` - overrides the state filename when _writing_ new state snapshots. If you use `-state` without also using `-state-out` then OpenTofu will use the `-state` filename for both `-state` and `-state-out`, which means OpenTofu will overwrite the input file if it creates a new state snapshot. * `-backup=FILENAME` - overrides the default filename that the local backend would normally choose dynamically to create backup files when it writes new state. If you use `-state` without also using `-backup` then OpenTofu will use the `-state` filename as a filename prefix for generating a backup filename. You can use `-backup=-` (that is, set the filename to just the ASCII dash character) to disable the creation of backup files altogether. These three options are preserved for backward-compatibility with earlier workflows that predated the introduction of built-in remote state, where users would write wrapper scripts that fetch prior state before running OpenTofu and then save the new state after OpenTofu exits, in which case the three arguments would typically all be paths within a temporary directory used just for one operation. Because these old workflows predate the introduction of the possibility of [multiple workspaces](https://opentofu.org/docs/v1.10/language/state/workspaces/) , setting them overrides OpenTofu's usual behavior of selecting a different state filename based on the selected workspace. If you use all three of these options then the selected workspace has no effect on which filenames OpenTofu will select for state files, and so you'll need to select different filenames yourself if you wish to keep workspace state files distinct from one another. These three options have no effect for configurations that have a different backend type selected. We do not recommend using these options in new systems, even if you are running OpenTofu in automation. Instead, [select a different backend which supports remote state](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) and configure it within your root module, which ensures that everyone working on your configuration will automatically retrieve and store state in the correct shared location without any special command line options. * [Example Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/local/#example-configuration) * [Data Source Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/local/#data-source-configuration) * [Configuration variables](https://opentofu.org/docs/v1.10/language/settings/backends/local/#configuration-variables) * [Command Line Arguments](https://opentofu.org/docs/v1.10/language/settings/backends/local/#command-line-arguments) --- # The count Meta-Argument | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/meta-arguments/count/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page The `count` Meta-Argument ========================= Note A given resource or module block cannot use both `count` and `for_each`. By default, a [resource block](https://opentofu.org/docs/v1.10/language/resources/syntax/) configures one real infrastructure object. (Similarly, a [module block](https://opentofu.org/docs/v1.10/language/modules/syntax/) includes a child module's contents into the configuration one time.) However, sometimes you want to manage several similar objects (like a fixed pool of compute instances) without writing a separate block for each one. OpenTofu has two ways to do this: `count` and [`for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) . If a resource or module block includes a `count` argument whose value is a whole number, OpenTofu will create that many instances. Basic Syntax[​](https://opentofu.org/docs/v1.10/language/meta-arguments/count/#basic-syntax "Direct link to Basic Syntax") --------------------------------------------------------------------------------------------------------------------------- `count` is a meta-argument defined by the OpenTofu language. It can be used with modules and with every resource type. The `count` meta-argument accepts a whole number, and creates that many instances of the resource or module. Each instance has a distinct infrastructure object associated with it, and each is separately created, updated, or destroyed when the configuration is applied. Code Block resource "aws_instance" "server" { count = 4 # create four similar EC2 instances ami = "ami-a1b2c3d4" instance_type = "t2.micro" tags = { Name = "Server ${count.index}" }} The `count` Object[​](https://opentofu.org/docs/v1.10/language/meta-arguments/count/#the-count-object "Direct link to the-count-object") ----------------------------------------------------------------------------------------------------------------------------------------- In blocks where `count` is set, an additional `count` object is available in expressions, so you can modify the configuration of each instance. This object has one attribute: * `count.index` β€”Β The distinct index number (starting with `0`) corresponding to this instance. Using Expressions in `count`[​](https://opentofu.org/docs/v1.10/language/meta-arguments/count/#using-expressions-in-count "Direct link to using-expressions-in-count") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- The `count` meta-argument accepts numeric [expressions](https://opentofu.org/docs/v1.10/language/expressions/) . However, unlike most arguments, the `count` value must be known _before_ OpenTofu performs any remote resource actions. This means `count` can't refer to any resource attributes that aren't known until after a configuration is applied (such as a unique ID generated by the remote API when an object is created). Referring to Instances[​](https://opentofu.org/docs/v1.10/language/meta-arguments/count/#referring-to-instances "Direct link to Referring to Instances") --------------------------------------------------------------------------------------------------------------------------------------------------------- When `count` is set, OpenTofu distinguishes between the block itself and the multiple _resource or module instances_ associated with it. Instances are identified by an index number, starting with `0`. * `.` or `module.` (for example, `aws_instance.server`) refers to the resource block. * `.[]` or `module.[]` (for example, `aws_instance.server[0]`, `aws_instance.server[1]`, etc.) refers to individual instances. This is different from resources and modules without `count` or `for_each`, which can be referenced without an index or key. Similarly, resources from child modules with multiple instances are prefixed with `module.[]` when displayed in plan output and elsewhere in the UI. For a module without `count` or `for_each`, the address will not contain the module index as the module's name suffices to reference the module. Note Within nested `provisioner` or `connection` blocks, the special `self` object refers to the current _resource instance,_ not the resource block as a whole. When to Use `for_each` Instead of `count`[​](https://opentofu.org/docs/v1.10/language/meta-arguments/count/#when-to-use-for_each-instead-of-count "Direct link to when-to-use-for_each-instead-of-count") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If your instances are almost identical, `count` is appropriate. If some of their arguments need distinct values that can't be directly derived from an integer, it's safer to use `for_each`. Before `for_each` was available, it was common to derive `count` from the length of a list and use `count.index` to look up the original list value: Code Block variable "subnet_ids" { type = list(string)}resource "aws_instance" "server" { # Create one instance for each subnet count = length(var.subnet_ids) ami = "ami-a1b2c3d4" instance_type = "t2.micro" subnet_id = var.subnet_ids[count.index] tags = { Name = "Server ${count.index}" }} This was fragile, because the resource instances were still identified by their _index_ instead of the string values in the list. If an element was removed from the middle of the list, every instance _after_ that element would see its `subnet_id` value change, resulting in more remote object changes than intended. Using `for_each` gives the same flexibility without the extra churn. * [Basic Syntax](https://opentofu.org/docs/v1.10/language/meta-arguments/count/#basic-syntax) * [The `count` Object](https://opentofu.org/docs/v1.10/language/meta-arguments/count/#the-count-object) * [Using Expressions in `count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/#using-expressions-in-count) * [Referring to Instances](https://opentofu.org/docs/v1.10/language/meta-arguments/count/#referring-to-instances) * [When to Use `for_each` Instead of `count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/#when-to-use-for_each-instead-of-count) --- # Providers | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/providers/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Providers ========= OpenTofu relies on plugins called providers to interact with cloud providers, SaaS providers, and other APIs. OpenTofu configurations must declare which providers they require so that OpenTofu can install and use them. Additionally, some providers require configuration (like endpoint URLs or cloud regions) before they can be used. What Providers Do[​](https://opentofu.org/docs/v1.10/language/providers/#what-providers-do "Direct link to What Providers Do") ------------------------------------------------------------------------------------------------------------------------------- Each provider adds a set of [resource types](https://opentofu.org/docs/v1.10/language/resources/) and/or [data sources](https://opentofu.org/docs/v1.10/language/data-sources/) that OpenTofu can manage. Every resource type is implemented by a provider; without providers, OpenTofu can't manage any kind of infrastructure. Most providers configure a specific infrastructure platform (either cloud or self-hosted). Providers can also offer local utilities for tasks like generating random numbers for unique resource names. Where Providers Come From[​](https://opentofu.org/docs/v1.10/language/providers/#where-providers-come-from "Direct link to Where Providers Come From") ------------------------------------------------------------------------------------------------------------------------------------------------------- Providers are distributed separately from OpenTofu itself, and each provider has its own release cadence and version numbers. The [Public OpenTofu Registry](https://registry.opentofu.org/) is the main directory of publicly available providers, and hosts providers for most major infrastructure platforms. Provider Documentation[​](https://opentofu.org/docs/v1.10/language/providers/#provider-documentation "Direct link to Provider Documentation") ---------------------------------------------------------------------------------------------------------------------------------------------- Each provider has its own documentation, describing its resource types and their arguments. This documentation can be found in each provider's GitHub repository, and the documentation for many providers is also mirrored on [the Providers index in the Public OpenTofu Registry](https://search.opentofu.org/providers) . Provider documentation is versioned, so it's important to refer to the tag or release matching the version you are using. How to Use Providers[​](https://opentofu.org/docs/v1.10/language/providers/#how-to-use-providers "Direct link to How to Use Providers") ---------------------------------------------------------------------------------------------------------------------------------------- Providers are released separately from OpenTofu itself and have their own version numbers. In production we recommend constraining the acceptable provider versions in the configuration's provider requirements block, to make sure that `tofu init` does not install newer versions of the provider that are incompatible with the configuration. To use resources from a given provider, you need to include some information about it in your configuration. See the following pages for details: * [Provider Requirements](https://opentofu.org/docs/v1.10/language/providers/requirements/) documents how to declare providers so OpenTofu can install them. * [Provider Configuration](https://opentofu.org/docs/v1.10/language/providers/configuration/) documents how to configure settings for providers. * [Dependency Lock File](https://opentofu.org/docs/v1.10/language/files/dependency-lock/) documents an additional HCL file that can be included with a configuration, which tells OpenTofu to always use a specific set of provider versions. Provider Installation[​](https://opentofu.org/docs/v1.10/language/providers/#provider-installation "Direct link to Provider Installation") ------------------------------------------------------------------------------------------------------------------------------------------- * [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software) install providers as part of every run. * OpenTofu CLI finds and installs providers when [initializing a working directory](https://opentofu.org/docs/v1.10/cli/init/) . It can automatically download providers from a provider registry, or load them from a local mirror or cache. If you are using a persistent working directory, you must reinitialize whenever you change a configuration's providers. To save time and bandwidth, OpenTofu CLI supports an optional plugin cache. You can enable the cache using the `plugin_cache_dir` setting in [the CLI configuration file](https://opentofu.org/docs/v1.10/cli/config/config-file/) . To ensure OpenTofu always installs the same provider versions for a given configuration, you can use OpenTofu CLI to create a [dependency lock file](https://opentofu.org/docs/v1.10/language/files/dependency-lock/) and commit it to version control along with your configuration. If a lock file is present, OpenTofu CLI, and [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software) will all obey it when installing providers. How to Find Providers[​](https://opentofu.org/docs/v1.10/language/providers/#how-to-find-providers "Direct link to How to Find Providers") ------------------------------------------------------------------------------------------------------------------------------------------- To find providers for the infrastructure platforms you use, browse the [Public OpenTofu Registry](https://github.com/opentofu/registry/tree/main/providers) . Some providers on the Registry are developed and published by HashiCorp, some are published by platform maintainers, and some are published by users and volunteers. How to Develop Providers[​](https://opentofu.org/docs/v1.10/language/providers/#how-to-develop-providers "Direct link to How to Develop Providers") ---------------------------------------------------------------------------------------------------------------------------------------------------- Providers are written in Go, using the Terraform Plugin SDK. For more information on developing providers, see the [Plugin Development](https://developer.hashicorp.com/terraform/plugin) documentation. ### Running Acceptance Tests with OpenTofu CLI[​](https://opentofu.org/docs/v1.10/language/providers/#running-acceptance-tests-with-opentofu-cli "Direct link to Running Acceptance Tests with OpenTofu CLI") When testing with OpenTofu, additional steps are required to run acceptance tests against the OpenTofu CLI. Set the following environment variables before running your acceptance tests: Code Block TF_ACC_TERRAFORM_PATH="/path/to/opentofu"TF_ACC_PROVIDER_NAMESPACE="hashicorp"TF_ACC_PROVIDER_HOST="registry.opentofu.org" * [What Providers Do](https://opentofu.org/docs/v1.10/language/providers/#what-providers-do) * [Where Providers Come From](https://opentofu.org/docs/v1.10/language/providers/#where-providers-come-from) * [Provider Documentation](https://opentofu.org/docs/v1.10/language/providers/#provider-documentation) * [How to Use Providers](https://opentofu.org/docs/v1.10/language/providers/#how-to-use-providers) * [Provider Installation](https://opentofu.org/docs/v1.10/language/providers/#provider-installation) * [How to Find Providers](https://opentofu.org/docs/v1.10/language/providers/#how-to-find-providers) * [How to Develop Providers](https://opentofu.org/docs/v1.10/language/providers/#how-to-develop-providers) * [Running Acceptance Tests with OpenTofu CLI](https://opentofu.org/docs/v1.10/language/providers/#running-acceptance-tests-with-opentofu-cli) --- # The Module providers Meta-Argument | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page The Module `providers` Meta-Argument ==================================== In a [module call](https://opentofu.org/docs/v1.10/language/modules/syntax/) block, the optional `providers` meta-argument specifies which [provider configurations](https://opentofu.org/docs/v1.10/language/providers/configuration/) from the parent module will be available inside the child module. Code Block # The default "aws" configuration is used for AWS resources in the root# module where no explicit provider instance is selected.provider "aws" { region = "us-west-1"}# An alternate configuration is also defined for a different# region, using the alias "usw2".provider "aws" { alias = "usw2" region = "us-west-2"}# An example child module is instantiated with the alternate configuration,# so any AWS resources it defines will use the us-west-2 region.module "example" { source = "./example" providers = { aws = aws.usw2 }} Each module in an OpenTofu configuration has its own separate namespace of provider configurations, but a child module's namespace is populated with configurations from the root module, either inheriting the default provider configurations automatically or explicitly passing them from the parent using the `providers` argument. Default Behavior: Inherit Default Providers[​](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#default-behavior-inherit-default-providers "Direct link to Default Behavior: Inherit Default Providers") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If the child module does not declare any [configuration aliases](https://opentofu.org/docs/v1.10/language/modules/develop/providers/#provider-aliases-within-modules) , the `providers` argument is optional. If you omit it, a child module inherits all of the [default provider configurations](https://opentofu.org/docs/v1.10/language/providers/configuration/#default-provider-configurations) from its parent module. (Default provider configurations are any that don't use the `alias` argument.) If you specify a `providers` argument, it cancels this default behavior, and the child module will only have access to the provider configurations you specify. Usage and Behavior[​](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#usage-and-behavior "Direct link to Usage and Behavior") -------------------------------------------------------------------------------------------------------------------------------------------------------- The `providers` argument uses a map-like syntax delimited by braces (`{`, `}`). In the given mapping: * The keys are the provider configuration addresses that will be used inside the child module. * The values are provider instance addresses from the parent module. Both parts use [provider instance reference syntax](https://opentofu.org/docs/v1.10/language/providers/configuration/#referring-to-provider-instances) , which for alternative provider configurations appears as `.`. Within a child module, resources are assigned to provider configurations as normal β€” either OpenTofu chooses a default based on the name of the resource type, or the resource specifies an alternate configuration with the `provider` argument. If the module receives a `providers` map when it's called, the provider configuration names used within the module are effectively remapped to refer the specified configurations from the parent module. When to Specify Providers[​](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#when-to-specify-providers "Direct link to When to Specify Providers") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- There are two main reasons to use the `providers` argument: * Using different default provider configurations for a child module. * Configuring a module that requires multiple configurations of the same provider. ### Changing Default Provider Configurations[​](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#changing-default-provider-configurations "Direct link to Changing Default Provider Configurations") Most re-usable modules only use default provider configurations, which they can automatically inherit from their caller when `providers` is omitted. However, in OpenTofu configurations that use multiple configurations of the same provider, you might want some child modules to use the default provider configuration and other ones to use an alternate. (This usually happens when using one configuration to manage resources in multiple different regions of the same cloud provider.) By using the `providers` argument (like in the code example above), you can accommodate this without needing to edit the child module. Although the code within the child module always refers to the default provider configuration, the actual configuration of that default can be different for each instance. ### Modules With Alternate Provider Configurations[​](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#modules-with-alternate-provider-configurations "Direct link to Modules With Alternate Provider Configurations") In rare cases, a single re-usable module might require multiple configurations of the same provider. For example, a module that configures connectivity between networks in two AWS regions is likely to need both a source and a destination region. In that case, the root module may look something like this: Code Block provider "aws" { alias = "usw1" region = "us-west-1"}provider "aws" { alias = "usw2" region = "us-west-2"}module "tunnel" { source = "./tunnel" providers = { aws.src = aws.usw1 aws.dst = aws.usw2 }} Non-default provider configurations are never automatically inherited, so any module that works like this will always need a `providers` argument. The documentation for the module should specify all of the provider configuration names it needs. ### Module instances with differing provider instances[​](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#module-instances-with-differing-provider-instances "Direct link to Module instances with differing provider instances") When you write a `provider` block using [the `for_each` meta-argument](https://opentofu.org/docs/v1.10/language/providers/configuration/#for_each-multiple-instances-of-a-provider-configuration) the provider configuration dynamically declares zero or more provider instances. If you also write a `module` block that uses `for_each` you can set its provider configuration addresses to refer to dynamically-chosen instances of a multi-instance provider configuration, which allows instantiating a module once per provider instance. For example, you might instantiate a module for each of a number of different AWS regions, declaring foundational infrastructure across all of the regions you use, with the module itself using only one default provider configuration that differs for each module instance: Code Block variable "aws_regions" { type = map(object({ vpc_cidr_block = string }))}provider "aws" { alias = "by_region" for_each = var.aws_regions region = each.key}module "per_region" { source = "./per-region" # This expression filters var.aws_regions to include only # the elements whose value is not null. Refer to the # warning in the text below for more information. for_each = { for region, config in var.aws_regions : region => config if config != null } providers = { aws = aws.by_region[each.key] } region_name = each.key vpc_cidr_block = each.value.vpc_cidr_block} The module in `./per-region` should be written so that all of its AWS resources are bound to that module's default configuration for the AWS provider. The `providers` argument in the `module` block ensures that each instance of the module has its default configuration for the AWS provider bound to a different instance of `aws.by_region`. All instances of the module must refer to instances of the same provider configuration: only the expression in brackets (`each.key` in the above example) can vary between the instances of the module. Warning **The `for_each` expression for a resource must not exactly match the `for_each` expression for its associated provider configuration.** OpenTofu uses a provider instance to plan and apply _all_ actions related to a resource instance, including destroying a resource instance that has been removed from the configuration. Therefore a provider instance passed into a child module that will declare resources associated with that provider instance must always remain in the configuration for at least one more plan/apply round after the module instance has been removed, or OpenTofu will fail to plan to destroy the resource instances declared in the module. You can find more information on this constraint in [Referring to Provider Instances](https://opentofu.org/docs/v1.10/language/providers/configuration/#referring-to-provider-instances) . More Information for Module Developers[​](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#more-information-for-module-developers "Direct link to More Information for Module Developers") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- For more details and guidance about working with providers inside a re-usable child module, see [Module Development: Providers Within Modules](https://opentofu.org/docs/v1.10/language/modules/develop/providers/) . * [Default Behavior: Inherit Default Providers](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#default-behavior-inherit-default-providers) * [Usage and Behavior](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#usage-and-behavior) * [When to Specify Providers](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#when-to-specify-providers) * [Changing Default Provider Configurations](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#changing-default-provider-configurations) * [Modules With Alternate Provider Configurations](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#modules-with-alternate-provider-configurations) * [Module instances with differing provider instances](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#module-instances-with-differing-provider-instances) * [More Information for Module Developers](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#more-information-for-module-developers) --- # OpenTofu Settings | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page OpenTofu Settings ================= The special `terraform` configuration block type is used to configure some behaviors of OpenTofu itself, such as requiring a minimum OpenTofu version to apply your configuration. Note As a part of [OpenTofu v1.x Compatibility Promises](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/) , the `terraform` block stays as-is. A `tofu` block may be introduced in the future, but it doesn't exist yet. OpenTofu `terraform` Block Syntax[​](https://opentofu.org/docs/v1.10/language/settings/#opentofu-terraform-block-syntax "Direct link to opentofu-terraform-block-syntax") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu settings are gathered together into `terraform` blocks: Code Block terraform { # ...} Each `terraform` block can contain a number of settings related to OpenTofu's behavior. Within a `terraform` block, only constant values can be used; arguments may not refer to named objects such as resources, input variables, etc, and may not use any of the OpenTofu language built-in functions. The various options supported within a `terraform` block are described in the following sections. Configuring an OpenTofu Backend[​](https://opentofu.org/docs/v1.10/language/settings/#configuring-an-opentofu-backend "Direct link to Configuring an OpenTofu Backend") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ The nested `backend` block configures which state backend OpenTofu should use. The syntax and behavior of the `backend` block is described in [Backend Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) . Specifying a Required OpenTofu Version[​](https://opentofu.org/docs/v1.10/language/settings/#specifying-a-required-opentofu-version "Direct link to Specifying a Required OpenTofu Version") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The `required_version` setting accepts a [version constraint string](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/) , which specifies which versions of OpenTofu can be used with your configuration. If the running version of OpenTofu doesn't match the constraints specified, OpenTofu will produce an error and exit without taking any further actions. When you use [child modules](https://opentofu.org/docs/v1.10/language/modules/) , each module can specify its own version requirements. The requirements of all modules in the tree must be satisfied. Use OpenTofu version constraints in a collaborative environment to ensure that everyone is using a specific OpenTofu version, or using at least a minimum OpenTofu version that has behavior expected by the configuration. The `required_version` setting applies only to the version of OpenTofu CLI. OpenTofu's resource types are implemented by provider plugins, whose release cycles are independent of OpenTofu CLI and of each other. Use [the `required_providers` block](https://opentofu.org/docs/v1.10/language/providers/requirements/) to manage the expected versions for each provider you use. Specifying Provider Requirements[​](https://opentofu.org/docs/v1.10/language/settings/#specifying-provider-requirements "Direct link to Specifying Provider Requirements") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The `required_providers` block specifies all of the providers required by the current module, mapping each local provider name to a source address and a version constraint. Code Block terraform { required_providers { aws = { version = ">= 2.7.0" source = "hashicorp/aws" } }} For more information, see [Provider Requirements](https://opentofu.org/docs/v1.10/language/providers/requirements/) . Experimental Language Features[​](https://opentofu.org/docs/v1.10/language/settings/#experimental-language-features "Direct link to Experimental Language Features") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- The OpenTofu team will sometimes introduce new language features initially via an opt-in experiment, so that the community can try the new feature and give feedback on it prior to it becoming a backward-compatibility constraint. In releases where experimental features are available, you can enable them on a per-module basis by setting the `experiments` argument inside a `tofu` block: Code Block terraform { experiments = [example]} The above would opt in to an experiment named `example`, assuming such an experiment were available in the current OpenTofu version. Experiments are subject to arbitrary changes in later releases and, depending on the outcome of the experiment, may change drastically before final release or may not be released in stable form at all. Such breaking changes may appear even in minor and patch releases. We do not recommend using experimental features in OpenTofu modules intended for production use. In order to make that explicit and to avoid module callers inadvertently depending on an experimental feature, any module with experiments enabled will generate a warning on every `tofu plan` or `tofu apply`. If you want to try experimental features in a shared module, we recommend enabling the experiment only in alpha or beta releases of the module. The introduction and completion of experiments is reported in [OpenTofu's changelog](https://github.com/opentofu/opentofu/blob/main/CHANGELOG.md) , so you can watch the release notes there to discover which experiment keywords, if any, are available in a particular OpenTofu release. Passing Metadata to Providers[​](https://opentofu.org/docs/v1.10/language/settings/#passing-metadata-to-providers "Direct link to Passing Metadata to Providers") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ The `terraform` block can have a nested `provider_meta` block for each provider a module is using, if the provider defines a schema for it. This allows the provider to receive module-specific information, and is primarily intended for modules distributed by the same vendor as the associated provider. For more information, see [Provider Metadata](https://opentofu.org/docs/v1.10/internals/provider-meta/) . * [OpenTofu `terraform` Block Syntax](https://opentofu.org/docs/v1.10/language/settings/#opentofu-terraform-block-syntax) * [Configuring an OpenTofu Backend](https://opentofu.org/docs/v1.10/language/settings/#configuring-an-opentofu-backend) * [Specifying a Required OpenTofu Version](https://opentofu.org/docs/v1.10/language/settings/#specifying-a-required-opentofu-version) * [Specifying Provider Requirements](https://opentofu.org/docs/v1.10/language/settings/#specifying-provider-requirements) * [Experimental Language Features](https://opentofu.org/docs/v1.10/language/settings/#experimental-language-features) * [Passing Metadata to Providers](https://opentofu.org/docs/v1.10/language/settings/#passing-metadata-to-providers) --- # The terraform_data Managed Resource Type | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/resources/tf-data/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page The `terraform_data` Managed Resource Type ========================================== The `terraform_data` implements the standard resource lifecycle, but does not directly take any other actions. You can use the `terraform_data` resource without requiring or configuring a provider. It is always available through a built-in provider with the [source address](https://opentofu.org/docs/v1.10/language/providers/requirements/#source-addresses) `terraform.io/builtin/terraform`. The `terraform_data` resource is useful for storing values which need to follow a manage resource lifecycle, and for triggering provisioners when there is no other logical managed resource in which to place them. Example Usage (data for `replace_triggered_by`)[​](https://opentofu.org/docs/v1.10/language/resources/tf-data/#example-usage-data-for-replace_triggered_by "Direct link to example-usage-data-for-replace_triggered_by") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [The `replace_triggered_by` lifecycle argument](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/#replace_triggered_by) requires all of the given addresses to be for resources, because the decision to force replacement is based on the planned actions for all of the mentioned resources. Plain data values such as [Local Values](https://opentofu.org/docs/v1.10/language/values/locals/) and [Input Variables](https://opentofu.org/docs/v1.10/language/values/variables/) don't have any side-effects to plan against and so they aren't valid in `replace_triggered_by`. You can use `terraform_data`'s behavior of planning an action each time `input` changes to _indirectly_ use a plain value to trigger replacement. Code Block variable "revision" { default = 1}resource "terraform_data" "replacement" { input = var.revision}# This resource has no convenient attribute which forces replacement,# but can now be replaced by any change to the revision variable value.resource "example_database" "test" { lifecycle { replace_triggered_by = [terraform_data.replacement] }} Example Usage (`null_resource` replacement)[​](https://opentofu.org/docs/v1.10/language/resources/tf-data/#example-usage-null_resource-replacement "Direct link to example-usage-null_resource-replacement") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block resource "aws_instance" "web" { # ...}resource "aws_instance" "database" { # ...}# A use-case for terraform_data is as a do-nothing container# for arbitrary actions taken by a provisioner.resource "terraform_data" "bootstrap" { triggers_replace = [ aws_instance.web.id, aws_instance.database.id ] provisioner "local-exec" { command = "bootstrap-hosts.sh" }} `moved` block can be used to migrate from the `null_resource` to the `terraform_data` resource. [Migration guide](https://search.opentofu.org/provider/hashicorp/null/latest/docs/guides/terraform-migration) Argument Reference[​](https://opentofu.org/docs/v1.10/language/resources/tf-data/#argument-reference "Direct link to Argument Reference") ------------------------------------------------------------------------------------------------------------------------------------------ The following arguments are supported: * `input` - (Optional) A value which will be stored in the instance state, and reflected in the `output` attribute after apply. * `triggers_replace` - (Optional) A value which is stored in the instance state, and will force replacement when the value changes. Attributes Reference[​](https://opentofu.org/docs/v1.10/language/resources/tf-data/#attributes-reference "Direct link to Attributes Reference") ------------------------------------------------------------------------------------------------------------------------------------------------ In addition to the above, the following attributes are exported: * `id` - A string value unique to the resource instance. * `output` - The computed value derived from the `input` argument. During a plan where `output` is unknown, it will still be of the same type as `input`. * [Example Usage (data for `replace_triggered_by`)](https://opentofu.org/docs/v1.10/language/resources/tf-data/#example-usage-data-for-replace_triggered_by) * [Example Usage (`null_resource` replacement)](https://opentofu.org/docs/v1.10/language/resources/tf-data/#example-usage-null_resource-replacement) * [Argument Reference](https://opentofu.org/docs/v1.10/language/resources/tf-data/#argument-reference) * [Attributes Reference](https://opentofu.org/docs/v1.10/language/resources/tf-data/#attributes-reference) --- # Provisioner Connection Settings | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provisioner Connection Settings =============================== Most provisioners require access to the remote resource via SSH or WinRM and expect a nested `connection` block with details about how to connect. Important Use provisioners as a last resort. There are better alternatives for most situations. Refer to [Declaring Provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/) for more details. Connection Block[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#connection-block "Direct link to Connection Block") ---------------------------------------------------------------------------------------------------------------------------------------------------- You can create one or more `connection` blocks that describe how to access the remote resource. One use case for providing multiple connections is to have an initial provisioner connect as the `root` user to set up user accounts and then have subsequent provisioners connect as a user with more limited permissions. Connection blocks don't take a block label and can be nested within either a `resource` or a `provisioner`. * A `connection` block nested directly within a `resource` affects all of that resource's provisioners. * A `connection` block nested in a `provisioner` block only affects that provisioner and overrides any resource-level connection settings. Since the SSH connection type is most often used with newly-created remote resources, validation of SSH host keys is disabled by default. If this is not acceptable, you can establish a separate mechanism for key distribution and explicitly set the `host_key` argument (details below) to verify against a specific key or signing CA. ### Example usage[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#example-usage "Direct link to Example usage") Code Block # Copies the file as the root user using SSHprovisioner "file" { source = "conf/myapp.conf" destination = "/etc/myapp.conf" connection { type = "ssh" user = "root" password = "${var.root_password}" host = "${var.host}" }}# Copies the file as the Administrator user using WinRMprovisioner "file" { source = "conf/myapp.conf" destination = "C:/App/myapp.conf" connection { type = "winrm" user = "Administrator" password = "${var.admin_password}" host = "${var.host}" }} ### The `self` Object[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#the-self-object "Direct link to the-self-object") Expressions in `connection` blocks cannot refer to their parent resource by name. References create dependencies, and referring to a resource by name within its own block would create a dependency cycle. Instead, expressions can use the `self` object, which represents the connection's parent resource and has all of that resource's attributes. For example, use `self.public_ip` to reference an `aws_instance`'s `public_ip` attribute. ### Argument Reference[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#argument-reference "Direct link to Argument Reference") The `connection` block supports the following arguments. Some arguments are only supported by either the SSH or the WinRM connection type. | Argument | Connection Type | Description | Default | | --- | --- | --- | --- | | `type` | Both | The connection type. Valid values are `"ssh"` and `"winrm"`. Provisioners typically assume that the remote system runs Microsoft Windows when using WinRM. Behaviors based on the SSH `target_platform` will force Windows-specific behavior for WinRM, unless otherwise specified. | `"ssh"` | | `user` | Both | The user to use for the connection. | `root` for type `"ssh"`
`Administrator` for type `"winrm"` | | `password` | Both | The password to use for the connection. | | | `host` | Both | **Required** - The address of the resource to connect to. | | | `port` | Both | The port to connect to. | `22` for type `"ssh"`
`5985` for type `"winrm"` | | `timeout` | Both | The timeout to wait for the connection to become available. Should be provided as a string (e.g., `"30s"` or `"5m"`.) | `"5m"` | | `script_path` | Both | The path used to copy scripts meant for remote execution. Refer to [How Provisioners Execute Remote Scripts](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#how-provisioners-execute-remote-scripts)
below for more details. | (details below) | | `private_key` | SSH | The contents of an SSH key to use for the connection. These can be loaded from a file on disk using [the `file` function](https://opentofu.org/docs/v1.10/language/functions/file/)
. This takes preference over `password` if provided. | | | `certificate` | SSH | The contents of a signed CA Certificate. The certificate argument must be used in conjunction with a `private_key`. These can be loaded from a file on disk using the [the `file` function](https://opentofu.org/docs/v1.10/language/functions/file/)
. | | | `agent` | SSH | Set to `false` to disable using `ssh-agent` to authenticate. On Windows the only supported SSH authentication agent is [Pageant](http://the.earth.li/~sgtatham/putty/0.66/htmldoc/Chapter9.html#pageant)
. | | | `agent_identity` | SSH | The preferred identity from the ssh agent for authentication. | | | `host_key` | SSH | The public key from the remote host or the signing CA, used to verify the connection. | | | `target_platform` | SSH | The target platform to connect to. Valid values are `"windows"` and `"unix"`. If the platform is set to `windows`, the default `script_path` is `c:\windows\temp\terraform_%RAND%.cmd`, assuming [the SSH default shell](https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_server_configuration#configuring-the-default-shell-for-openssh-in-windows)
is `cmd.exe`. If the SSH default shell is PowerShell, set `script_path` to `"c:/windows/temp/terraform_%RAND%.ps1"` | `"unix"` | | `https` | WinRM | Set to `true` to connect using HTTPS instead of HTTP. | | | `insecure` | WinRM | Set to `true` to skip validating the HTTPS certificate chain. | | | `use_ntlm` | WinRM | Set to `true` to use NTLM authentication rather than default (basic authentication), removing the requirement for basic authentication to be enabled within the target guest. Refer to [Authentication for Remote Connections](https://docs.microsoft.com/en-us/windows/win32/winrm/authentication-for-remote-connections)
in the Windows App Development documentation for more details. | | | `cacert` | WinRM | The CA certificate to validate against. | | Connecting through a Bastion Host with SSH[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#connecting-through-a-bastion-host-with-ssh "Direct link to Connecting through a Bastion Host with SSH") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The `ssh` connection also supports the following arguments to connect indirectly with a [bastion host](https://en.wikipedia.org/wiki/Bastion_host) . | Argument | Description | Default | | --- | --- | --- | | `bastion_host` | Setting this enables the bastion Host connection. The provisioner will connect to `bastion_host` first, and then connect from there to `host`. | | | `bastion_host_key` | The public key from the remote host or the signing CA, used to verify the host connection. | | | `bastion_port` | The port to use connect to the bastion host. | The value of the `port` field. | | `bastion_user` | The user for the connection to the bastion host. | The value of the `user` field. | | `bastion_password` | The password to use for the bastion host. | The value of the `password` field. | | `bastion_private_key` | The contents of an SSH key file to use for the bastion host. These can be loaded from a file on disk using [the `file` function](https://opentofu.org/docs/v1.10/language/functions/file/)
. | The value of the `private_key` field. | | `bastion_certificate` | The contents of a signed CA Certificate. The certificate argument must be used in conjunction with a `bastion_private_key`. These can be loaded from a file on disk using the [the `file` function](https://opentofu.org/docs/v1.10/language/functions/file/)
. | | Connection through a HTTP Proxy with SSH[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#connection-through-a-http-proxy-with-ssh "Direct link to Connection through a HTTP Proxy with SSH") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The `ssh` connection also supports the following fields to facilitate connections by SSH over HTTP proxy. | Argument | Description | Default | | --- | --- | --- | | `proxy_scheme` | http or https | | | `proxy_host` | Setting this enables the SSH over HTTP connection. This host will be connected to first, and then the `host` or `bastion_host` connection will be made from there. | | | `proxy_port` | The port to use connect to the proxy host. | | | `proxy_user_name` | The username to use connect to the private proxy host. This argument should be specified only if authentication is required for the HTTP Proxy server. | | | `proxy_user_password` | The password to use connect to the private proxy host. This argument should be specified only if authentication is required for the HTTP Proxy server. | | How Provisioners Execute Remote Scripts[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#how-provisioners-execute-remote-scripts "Direct link to How Provisioners Execute Remote Scripts") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Provisioners which execute commands on a remote system via a protocol such as SSH typically achieve that by uploading a script file to the remote system and then asking the default shell to execute it. Provisioners use this strategy because it then allows you to use all of the typical scripting techniques supported by that shell, including preserving environment variable values and other context between script statements. However, this approach does have some consequences which can be relevant in some unusual situations, even though this is just an implementation detail in typical use. Most importantly, there must be a suitable location in the remote filesystem where the provisioner can create the script file. By default, OpenTofu chooses a path containing a random number using the following patterns depending on how `target_platform` is set: * `"unix"`: `/tmp/terraform_%RAND%.sh` * `"windows"`: `C:/windows/temp/terraform_%RAND%.cmd` In both cases above, the provisioner replaces the sequence `%RAND%` with some randomly-chosen decimal digits. Provisioners cannot react directly to remote environment variables such as `TMPDIR` or use functions like `mktemp` because they run on the system where OpenTofu is running, not on the remote system. Therefore if your remote system doesn't use the filesystem layout expected by these default paths then you can override it using the `script_path` option in your `connection` block: Code Block connection { # ... script_path = "H:/tofu-temp/script_%RAND%.sh"} As with the default patterns, provisioners will replace the sequence `%RAND%` with randomly-selected decimal digits, to reduce the likelihood of collisions between multiple provisioners running concurrently. If your target system is running Windows, we recommend using forward slashes instead of backslashes, despite the typical convention on Windows, because the OpenTofu language uses backslash as the quoted string escape character. ### Executing Scripts using SSH/SCP[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#executing-scripts-using-sshscp "Direct link to Executing Scripts using SSH/SCP") When using the SSH protocol, provisioners upload their script files using the Secure Copy Protocol (SCP), which requires that the remote system have the `scp` service program installed to act as the server for that protocol. Provisioners will pass the chosen script path (after `%RAND%` expansion) directly to the remote `scp` process, which is responsible for interpreting it. With the default configuration of `scp` as distributed with OpenSSH, you can place temporary scripts in the home directory of the remote user by specifying a relative path: Code Block connection { type = "ssh" # ... script_path = "tofu_provisioner_%RAND%.sh"} * [Connection Block](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#connection-block) * [Example usage](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#example-usage) * [The `self` Object](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#the-self-object) * [Argument Reference](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#argument-reference) * [Connecting through a Bastion Host with SSH](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#connecting-through-a-bastion-host-with-ssh) * [Connection through a HTTP Proxy with SSH](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#connection-through-a-http-proxy-with-ssh) * [How Provisioners Execute Remote Scripts](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#how-provisioners-execute-remote-scripts) * [Executing Scripts using SSH/SCP](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/#executing-scripts-using-sshscp) --- # Variables and Outputs | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/values/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Variables and Outputs ===================== The OpenTofu language includes a few kinds of blocks for requesting or publishing named values. * [Input Variables](https://opentofu.org/docs/v1.10/language/values/variables/) serve as parameters for a module, so users can customize behavior without editing the source. * [Output Values](https://opentofu.org/docs/v1.10/language/values/outputs/) are like return values for a module. * [Local Values](https://opentofu.org/docs/v1.10/language/values/locals/) are a convenience feature for assigning a short name to an expression. --- # Writing and Modifying OpenTofu Code | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/code/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Writing and Modifying OpenTofu Code =================================== The [OpenTofu language](https://opentofu.org/docs/v1.11/language/) is OpenTofu's primary user interface, and all of OpenTofu's workflows rely on configurations written in the OpenTofu language. OpenTofu CLI includes several commands to make OpenTofu code more convenient to work with. Integrating these commands into your editing workflow can potentially save you time and effort. * [The `tofu console` command](https://opentofu.org/docs/v1.11/cli/commands/console/) starts an interactive shell for evaluating OpenTofu [expressions](https://opentofu.org/docs/v1.11/language/expressions/) , which can be a faster way to verify that a particular resource argument results in the value you expect. * [The `tofu fmt` command](https://opentofu.org/docs/v1.11/cli/commands/fmt/) rewrites OpenTofu configuration files to a canonical format and style, so you don't have to waste time making minor adjustments for readability and consistency. It works well as a pre-commit hook in your version control system. * [The `tofu validate` command](https://opentofu.org/docs/v1.11/cli/commands/validate/) validates the syntax and arguments of the OpenTofu configuration files in a directory, including argument and attribute names and types for resources and modules. The `plan` and `apply` commands automatically validate a configuration before performing any other work, so `validate` isn't a crucial part of the core workflow, but it can be very useful as a pre-commit hook or as part of a continuous integration pipeline. --- # Backend Type: kubernetes | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/backends/kubernetes/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Backend Type: kubernetes ======================== Note This backend is limited by Kubernetes' maximum Secret size of 1MB. See [Secret restrictions](https://kubernetes.io/docs/concepts/configuration/secret/#restrictions) for details. Stores the state in a [Kubernetes secret](https://kubernetes.io/docs/concepts/configuration/secret/) . This backend supports [state locking](https://opentofu.org/docs/v1.10/language/state/locking/) , with locking done using a Lease resource. Example Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/kubernetes/#example-configuration "Direct link to Example Configuration") -------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block terraform { backend "kubernetes" { secret_suffix = "state" config_path = "~/.kube/config" }} This assumes the user/service account running OpenTofu has [permissions](https://kubernetes.io/docs/reference/access-authn-authz/authorization/) to read/write secrets in the [namespace](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) used to store the secret. If the `config_path` or `config_paths` attribute is set the backend will attempt to use a [kubeconfig file](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) to gain access to the cluster. If the `in_cluster_config` flag is set the backend will attempt to use a [service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) to access the cluster. This can be used if OpenTofu is being run from within a pod running in the Kubernetes cluster. For most use cases either `in_cluster_config`, `config_path`, or `config_paths` will need to be set. If all flags are set the configuration at `config_path` will be used. Note that for the access credentials we recommend using a [partial configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#partial-configuration) . Example Referencing[​](https://opentofu.org/docs/v1.10/language/settings/backends/kubernetes/#example-referencing "Direct link to Example Referencing") -------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block data "terraform_remote_state" "foo" { backend = "kubernetes" config = { secret_suffix = "state" load_config_file = true }} Configuration Variables[​](https://opentofu.org/docs/v1.10/language/settings/backends/kubernetes/#configuration-variables "Direct link to Configuration Variables") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- Warning We recommend using environment variables to supply credentials and other sensitive data. If you use `-backend-config` or hardcode these values directly in your configuration, OpenTofu will include these values in both the `.terraform` subdirectory and in plan files. Refer to [Credentials and Sensitive Data](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#credentials-and-sensitive-data) for details. The following configuration options are supported: * `secret_suffix` - (Required) Suffix used when creating secrets. Secrets will be named in the format: `tfstate-{workspace}-{secret_suffix}`. * `labels` - (Optional) Map of additional labels to be applied to the secret and lease. * `namespace` - (Optional) Namespace to store the secret and lease in. Can be sourced from `KUBE_NAMESPACE`. * `in_cluster_config` - (Optional) Used to authenticate to the cluster from inside a pod. Can be sourced from `KUBE_IN_CLUSTER_CONFIG`. * `host` - (Optional) The hostname (in form of URI) of Kubernetes master. Can be sourced from `KUBE_HOST`. Defaults to `https://localhost`. * `username` - (Optional) The username to use for HTTP basic authentication when accessing the Kubernetes master endpoint. Can be sourced from `KUBE_USER`. * `password` - (Optional) The password to use for HTTP basic authentication when accessing the Kubernetes master endpoint. Can be sourced from `KUBE_PASSWORD`. * `insecure` - (Optional) Whether server should be accessed without verifying the TLS certificate. Can be sourced from `KUBE_INSECURE`. Defaults to `false`. * `client_certificate` - (Optional) PEM-encoded client certificate for TLS authentication. Can be sourced from `KUBE_CLIENT_CERT_DATA`. * `client_key` - (Optional) PEM-encoded client certificate key for TLS authentication. Can be sourced from `KUBE_CLIENT_KEY_DATA`. * `cluster_ca_certificate` - (Optional) PEM-encoded root certificates bundle for TLS authentication. Can be sourced from `KUBE_CLUSTER_CA_CERT_DATA`. * `config_path` - (Optional) Path to the kube config file. Can be sourced from `KUBE_CONFIG_PATH`. * `config_paths` - (Optional) List of paths to kube config files. Can be sourced from `KUBE_CONFIG_PATHS`. * `config_context` - (Optional) Context to choose from the config file. Can be sourced from `KUBE_CTX`. * `config_context_auth_info` - (Optional) Authentication info context of the kube config (name of the kubeconfig user, `--user` flag in `kubectl`). Can be sourced from `KUBE_CTX_AUTH_INFO`. * `config_context_cluster` - (Optional) Cluster context of the kube config (name of the kubeconfig cluster, `--cluster` flag in `kubectl`). Can be sourced from `KUBE_CTX_CLUSTER`. * `token` - (Optional) Token of your service account. Can be sourced from `KUBE_TOKEN`. * `exec` - (Optional) Configuration block to use an [exec-based credential plugin](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins) , e.g. call an external command to receive user credentials. * `api_version` - (Required) API version to use when decoding the ExecCredentials resource, e.g. `client.authentication.k8s.io/v1beta1`. * `command` - (Required) Command to execute. * `args` - (Optional) List of arguments to pass when executing the plugin. * `env` - (Optional) Map of environment variables to set when executing the plugin. * [Example Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/kubernetes/#example-configuration) * [Example Referencing](https://opentofu.org/docs/v1.10/language/settings/backends/kubernetes/#example-referencing) * [Configuration Variables](https://opentofu.org/docs/v1.10/language/settings/backends/kubernetes/#configuration-variables) --- # Providers Within Modules | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/modules/develop/providers/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Providers Within Modules ======================== In a configuration with multiple modules, there are some special considerations for how resources are associated with provider configurations. Each resource in the configuration must be associated with one provider configuration. Provider configurations, unlike most other concepts in OpenTofu, are global to an entire OpenTofu configuration and can be shared across module boundaries. Provider configurations can be defined only in a root module. Providers can be passed down to descendent modules in two ways: either _implicitly_ through inheritance, or _explicitly_ via the `providers` argument within a `module` block. These two options are discussed in more detail in the following sections. A module intended to be called by one or more other modules must not contain any `provider` blocks. A module containing its own provider configurations is not compatible with the `for_each`, `count`, and `depends_on` meta-arguments. Provider configurations are used for all operations on associated resources, including destroying remote objects and refreshing state. OpenTofu retains, as part of its state, a reference to the provider configuration that was most recently used to apply changes to each resource. When a `resource` block is removed from the configuration, or a dynamic instance of a resource is removed by modifying the value assigned to the `count` or `for_each` meta-argument, this record in the state will be used to locate the appropriate configuration because the resource instance's `provider` argument (if any) will no longer be present in the configuration. As a consequence, you must ensure that all resources that belong to a particular provider instance are destroyed before you can remove that provider instance from your configuration. If OpenTofu finds a resource instance tracked in the state whose provider instance is no longer declared in the configuration then it will return an error during planning, prompting you to reintroduce the provider instance. Provider Version Constraints in Modules[​](https://opentofu.org/docs/v1.10/language/modules/develop/providers/#provider-version-constraints-in-modules "Direct link to Provider Version Constraints in Modules") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Although provider _configurations_ are shared between modules, each module must declare its own [provider requirements](https://opentofu.org/docs/v1.10/language/providers/requirements/) , so that OpenTofu can ensure that there is a single version of the provider that is compatible with all modules in the configuration and to specify the [source address](https://opentofu.org/docs/v1.10/language/providers/requirements/#source-addresses) that serves as the global (module-agnostic) identifier for a provider. To declare that a module requires particular versions of a specific provider, use a `required_providers` block inside a `terraform` block: Code Block terraform { required_providers { aws = { source = "hashicorp/aws" version = ">= 2.7.0" } }} A provider requirement says, for example, "This module requires version v2.7.0 of the provider `hashicorp/aws` and will refer to it as `aws`." It doesn't, however, specify any of the configuration settings that determine what remote endpoints the provider will access, such as an AWS region; configuration settings come from provider _configurations_, and a particular overall OpenTofu configuration can potentially have [several different configurations for the same provider](https://opentofu.org/docs/v1.10/language/providers/configuration/#alias-multiple-provider-configurations) . Provider Aliases Within Modules[​](https://opentofu.org/docs/v1.10/language/modules/develop/providers/#provider-aliases-within-modules "Direct link to Provider Aliases Within Modules") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To declare multiple configuration names for a provider within a module, add the `configuration_aliases` argument: Code Block terraform { required_providers { aws = { source = "hashicorp/aws" version = ">= 2.7.0" configuration_aliases = [ aws.alternate ] } }} The above requirements are identical to the previous, with the addition of the alias provider configuration name `aws.alternate`, which can be referenced by resources using the `provider` argument. If you are writing a shared module, constrain only the minimum required provider version using a `>=` constraint. This should specify the minimum version containing the features your module relies on, and thus allow a user of your module to potentially select a newer provider version if other features are needed by other parts of their overall configuration. It is not currently possible to pass a provider configuration with multiple instances (that was declared using `for_each`) as a whole to a child module, although it is valid for the parent module to assign a single dynamic instance of a provider configuration to each instance of the module. Implicit Provider Inheritance[​](https://opentofu.org/docs/v1.10/language/modules/develop/providers/#implicit-provider-inheritance "Direct link to Implicit Provider Inheritance") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- For convenience in simple configurations, a child module automatically inherits [default provider configurations](https://opentofu.org/docs/v1.10/language/providers/configuration/#default-provider-configurations) from its parent. This means that explicit `provider` blocks appear only in the root module, and downstream modules can simply declare resources for that provider and have them automatically associated with the root provider configurations. For example, the root module might contain only a `provider` block and a `module` block to instantiate a child module: Code Block provider "aws" { region = "us-west-1"}module "child" { source = "./child"} The child module can then use any resource from this provider with no further provider configuration required: Code Block resource "aws_s3_bucket" "example" { bucket = "provider-inherit-example"} We recommend using this approach when a single configuration for each provider is sufficient for an entire configuration. Note Only provider configurations are inherited by child modules, not provider source or version requirements. Each module must [declare its own provider requirements](https://opentofu.org/docs/v1.10/language/providers/requirements/) . This is especially important for non-HashiCorp providers. In more complex situations there may be [multiple provider configurations](https://opentofu.org/docs/v1.10/language/providers/configuration/#alias-multiple-provider-configurations) , or a child module may need to use different provider settings than its parent. For such situations, you must pass providers explicitly. Passing Providers Explicitly[​](https://opentofu.org/docs/v1.10/language/modules/develop/providers/#passing-providers-explicitly "Direct link to Passing Providers Explicitly") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When child modules each need a different configuration of a particular provider, or where the child module requires a different provider configuration than its parent, you can use the `providers` argument within a `module` block to explicitly define which provider configurations are available to the child module. For example: Code Block # The default "aws" configuration is used for AWS resources in the root# module where no explicit provider instance is selected.provider "aws" { region = "us-west-1"}# An alternate configuration is also defined for a different# region, using the alias "usw2".provider "aws" { alias = "usw2" region = "us-west-2"}# An example child module is instantiated with the alternate configuration,# so any AWS resources it defines will use the us-west-2 region.module "example" { source = "./example" providers = { aws = aws.usw2 }} [The `providers` argument within a `module` block](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/) is similar to [the `provider` argument within a `resource` block](https://opentofu.org/docs/v1.10/language/meta-arguments/resource-provider/) , but is a mapping rather than a single string because a module may contain resources from many different providers. The keys of the `providers` map are provider configuration names as expected by the child module, and the values are the names of corresponding configurations in the _current_ module. Once the `providers` argument is used in a `module` block, it overrides all of the default inheritance behavior, so it is necessary to enumerate mappings for _all_ of the required providers. This is to avoid confusion and surprises that may result when mixing both implicit and explicit provider passing. Additional provider configurations (those with the `alias` argument set) are _never_ inherited automatically by child modules, and so must always be passed explicitly using the `providers` map. For example, a module that configures connectivity between networks in two AWS regions is likely to need both a source and a destination region. In that case, the root module may look something like this: Code Block provider "aws" { alias = "usw1" region = "us-west-1"}provider "aws" { alias = "usw2" region = "us-west-2"}module "tunnel" { source = "./tunnel" providers = { aws.src = aws.usw1 aws.dst = aws.usw2 }} The subdirectory `./tunnel` must then declare the configuration aliases for the provider so the calling module can pass configurations with these names in its `providers` argument: Code Block terraform { required_providers { aws = { source = "hashicorp/aws" version = ">= 2.7.0" configuration_aliases = [ aws.src, aws.dst ] } }} Each resource should then have its own `provider` attribute set to either `aws.src` or `aws.dst` to choose which of the two provider configurations to use. * [Provider Version Constraints in Modules](https://opentofu.org/docs/v1.10/language/modules/develop/providers/#provider-version-constraints-in-modules) * [Provider Aliases Within Modules](https://opentofu.org/docs/v1.10/language/modules/develop/providers/#provider-aliases-within-modules) * [Implicit Provider Inheritance](https://opentofu.org/docs/v1.10/language/modules/develop/providers/#implicit-provider-inheritance) * [Passing Providers Explicitly](https://opentofu.org/docs/v1.10/language/modules/develop/providers/#passing-providers-explicitly) --- # Syntax | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/syntax/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Syntax ====== The majority of the OpenTofu language documentation focuses on the practical uses of the language and the specific constructs it uses. The pages in this section offer a more abstract view of the OpenTofu language. * [Configuration Syntax](https://opentofu.org/docs/v1.10/language/syntax/configuration/) describes the native grammar of the OpenTofu language. * [JSON Configuration Syntax](https://opentofu.org/docs/v1.10/language/syntax/json/) documents how to represent OpenTofu language constructs in the pure JSON variant of the OpenTofu language. OpenTofu's JSON syntax is unfriendly to humans, but can be very useful when generating infrastructure as code with other systems that don't have a readily available HCL library. * [Style Conventions](https://opentofu.org/docs/v1.10/language/syntax/style/) documents some commonly accepted formatting guidelines for OpenTofu code. These conventions can be enforced automatically with [`tofu fmt`](https://opentofu.org/docs/v1.10/cli/commands/fmt/) . --- # Backend Type: COS | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/backends/cos/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Backend Type: COS ================= Stores the state as an object in a configurable prefix in a given bucket on [Tencent Cloud Object Storage](https://intl.cloud.tencent.com/product/cos) (COS). This backend supports [state locking](https://opentofu.org/docs/v1.10/language/state/locking/) . Storing your state in a COS bucket requires the following permissions: * `CreateTag`, `DeleteTag`, and `DescribeTags` on the tag key `tencentcloud-terraform-lock` * `Put`, `Get`, and `Delete` files for the specified bucket's prefix Warning It is highly recommended that you enable [Object Versioning](https://intl.cloud.tencent.com/document/product/436/19883) on the COS bucket to allow for state recovery in the case of accidental deletions and human error. Example Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/cos/#example-configuration "Direct link to Example Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block terraform { backend "cos" { region = "ap-guangzhou" bucket = "bucket-for-tofu-state-1258798060" prefix = "tofu/state" }} This assumes we have a [COS Bucket](https://registry.terraform.io/providers/tencentcloudstack/tencentcloud/latest/docs/resources/cos_bucket) created named `bucket-for-tofu-state-1258798060`, OpenTofu state will be written into the file `tofu/state/terraform.tfstate`. Data Source Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/cos/#data-source-configuration "Direct link to Data Source Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- To make use of the COS remote state in another configuration, use the [`terraform_remote_state` data source](https://opentofu.org/docs/v1.10/language/state/remote-state-data/) . Code Block data "terraform_remote_state" "foo" { backend = "cos" config = { region = "ap-guangzhou" bucket = "bucket-for-tofu-state-1258798060" prefix = "tofu/state" }} Configuration Variables[​](https://opentofu.org/docs/v1.10/language/settings/backends/cos/#configuration-variables "Direct link to Configuration Variables") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Warning We recommend using environment variables to supply credentials and other sensitive data. If you use `-backend-config` or hardcode these values directly in your configuration, OpenTofu will include these values in both the `.terraform` subdirectory and in plan files. Refer to [Credentials and Sensitive Data](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#credentials-and-sensitive-data) for details. The following configuration options or environment variables are supported: * `secret_id` - (Optional) Secret id of Tencent Cloud. It supports environment variables `TENCENTCLOUD_SECRET_ID`. * `secret_key` - (Optional) Secret key of Tencent Cloud. It supports environment variables `TENCENTCLOUD_SECRET_KEY`. * `security_token` - (Optional) TencentCloud Security Token of temporary access credentials. It supports environment variables `TENCENTCLOUD_SECURITY_TOKEN`. * `region` - (Optional) The region of the COS bucket. It supports environment variables `TENCENTCLOUD_REGION`. * `bucket` - (Required) The name of the COS bucket. You shall manually create it first. * `prefix` - (Optional) The directory for saving the state file in bucket. Default to "env:". * `key` - (Optional) The path for saving the state file in bucket. Defaults to `terraform.tfstate`. * `encrypt` - (Optional) Whether to enable server side encryption of the state file. If it is true, COS will use 'AES256' encryption algorithm to encrypt state file. * `acl` - (Optional) Object ACL to be applied to the state file, allows `private` and `public-read`. Defaults to `private`. * `accelerate` - (Optional) Whether to enable global Acceleration. Defaults to `false`. ### Assume Role[​](https://opentofu.org/docs/v1.10/language/settings/backends/cos/#assume-role "Direct link to Assume Role") If provided with an assume role, OpenTofu will attempt to assume this role using the supplied credentials. Assume role can be provided by adding an `assume_role` block in the cos backend block. * `assume_role` - (Optional) The `assume_role` block. If provided, OpenTofu will attempt to assume this role using the supplied credentials. The details of `assume_role` block as following: * `role_arn` - (Required) The ARN of the role to assume. It can be sourced from the `TENCENTCLOUD_ASSUME_ROLE_ARN`. * `session_name` - (Required) The session name to use when making the AssumeRole call. It can be sourced from the `TENCENTCLOUD_ASSUME_ROLE_SESSION_NAME`. * `session_duration` - (Required) The duration of the session when making the AssumeRole call. Its value ranges from 0 to 43200(seconds), and default is 7200 seconds. It can be sourced from the `TENCENTCLOUD_ASSUME_ROLE_SESSION_DURATION`. * `policy` - (Optional) A more restrictive policy when making the AssumeRole call. Its content must not contains `principal` elements. Notice: more syntax references, please refer to: [policies syntax logic](https://intl.cloud.tencent.com/document/product/598/10603) . Usage: Code Block terraform { backend "cos" { region = "ap-guangzhou" bucket = "bucket-for-tofu-state-{appid}" prefix = "tofu/state" assume_role { role_arn = "qcs::cam::uin/xxx:roleName/yyy" session_name = "my-session-name" session_duration = 3600 } }} In addition, these `assume_role` configurations can also be provided by environment variables. Usage: Code Block $ export TENCENTCLOUD_SECRET_ID="my-secret-id"$ export TENCENTCLOUD_SECRET_KEY="my-secret-key"$ export TENCENTCLOUD_REGION="ap-guangzhou"$ export TENCENTCLOUD_ASSUME_ROLE_ARN="qcs::cam::uin/xxx:roleName/yyy"$ export TENCENTCLOUD_ASSUME_ROLE_SESSION_NAME="my-session-name"$ export TENCENTCLOUD_ASSUME_ROLE_SESSION_DURATION=3600$ tofu plan * [Example Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/cos/#example-configuration) * [Data Source Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/cos/#data-source-configuration) * [Configuration Variables](https://opentofu.org/docs/v1.10/language/settings/backends/cos/#configuration-variables) * [Assume Role](https://opentofu.org/docs/v1.10/language/settings/backends/cos/#assume-role) --- # Initializing and Migrating | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/cloud/migrating/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Initializing and Migrating ========================== After [configuring cloud backend settings](https://opentofu.org/docs/v1.11/cli/cloud/settings/) for a working directory, you must run `tofu init` to finish setting up. If the working directory has no existing OpenTofu state, you can start using OpenTofu with a cloud backend right away. When you run `tofu init` in the following scenarios, OpenTofu will ask you to choose whether or not to migrate state from any existing workspaces. 1. [**Migrating from local state or state backends:**](https://opentofu.org/docs/v1.11/cli/cloud/migrating/#migrating-from-local-state-or-state-backends) If the working directory already has state data in one or more workspaces, OpenTofu will ask if you would like to migrate that state to new cloud backend workspaces. 2. [**Migrating from the `remote` backend:**](https://opentofu.org/docs/v1.11/cli/cloud/migrating/#migrating-from-the-remote-backend) If the working directory was already connected to a cloud backend with the `remote` backend, OpenTofu can continue using the same cloud backend workspaces. You will need to switch the `remote` backend block to the `cloud` block. Migrating from Local State or State Backends[​](https://opentofu.org/docs/v1.11/cli/cloud/migrating/#migrating-from-local-state-or-state-backends "Direct link to Migrating from Local State or State Backends") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If the working directory already has state data available (using either local state or a [state backend](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/) ), OpenTofu asks your approval to migrate that state to the cloud backend. You will need permission to manage workspaces in the destination cloud backend organization. This process is interactive and self-documenting, and resembles moving between state backends. OpenTofu may also prompt you to rename your workspaces during the migration, to either give a name to the unnamed `default` workspace (the cloud backend requires all workspaces to have a name) or give your workspace names more contextual information. Unlike OpenTofu CLI-only workspaces, which represent multiple environments associated with the same configuration (e.g. production, staging, development), cloud backend workspaces can represent totally independent configurations, and must have unique names within the cloud backend organization. Because of this, OpenTofu will prompt you to rename the working directory's workspaces according to a pattern relative to their existing names. This can indicate the fact that these specific workspaces share configuration. A typical strategy is `--` (e.g., `networking-prod-us-east`, `networking-staging-us-east`). Migrating from the `remote` Backend[​](https://opentofu.org/docs/v1.11/cli/cloud/migrating/#migrating-from-the-remote-backend "Direct link to migrating-from-the-remote-backend") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If the working directory was already connected to a cloud backend with the `remote` backend, OpenTofu can continue using the same cloud backend workspaces. The local names shown for those workspaces will change to match their remote names. The [`remote` backend](https://opentofu.org/docs/v1.11/language/settings/backends/remote/) was the primary implementation for cloud backends for Terraform versions 0.11.13 through 1.0.x. We recommend using the native `cloud` integration for OpenTofu and Terraform versions 1.1 or later, as it provides an improved user experience and various enhancements. ### Block Replacement[​](https://opentofu.org/docs/v1.11/cli/cloud/migrating/#block-replacement "Direct link to Block Replacement") When switching from the `remote` backend to a `cloud` block, OpenTofu will continue using the same set of cloud backend workspaces. Replace your `backend "remote"` block with an equivalent `cloud` block. #### Single Workspace[​](https://opentofu.org/docs/v1.11/cli/cloud/migrating/#single-workspace "Direct link to Single Workspace") If you were using a single workspace with the `name` argument, change the block label to `cloud`. Code Block terraform {- backend "remote" {+ cloud { organization = "my-org" workspaces { name = "my-app-prod" } } } #### Multiple Workspaces[​](https://opentofu.org/docs/v1.11/cli/cloud/migrating/#multiple-workspaces "Direct link to Multiple Workspaces") If you were using multiple workspaces with the `prefix` argument, replace it with a `cloud` block that uses the `tags` argument. You may specify any number of tags to distinguish the workspaces for your working directory, but a good starting point may be to use whatever the prefix was before. The tags you configure do not need to be present on the existing workspaces. When you initialize, OpenTofu will add the specified tags to the workspaces if necessary. Code Block terraform {- backend "remote" {+ cloud { organization = "my-org" workspaces {- prefix = "my-app-"+ tags = ["app:mine"] } } } Warning Because the `cloud` block does not support the `prefix` argument, once you migrate, you must refer to workspaces by their full name when using the OpenTofu CLI. For example, rather than `tofu workspace select prod`, you must run the command `tofu workspace select my-app-prod`. * [Migrating from Local State or State Backends](https://opentofu.org/docs/v1.11/cli/cloud/migrating/#migrating-from-local-state-or-state-backends) * [Migrating from the `remote` Backend](https://opentofu.org/docs/v1.11/cli/cloud/migrating/#migrating-from-the-remote-backend) * [Block Replacement](https://opentofu.org/docs/v1.11/cli/cloud/migrating/#block-replacement) --- # Backend Type: gcs | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Backend Type: gcs ================= Stores the state as an object in a configurable prefix in a pre-existing bucket on [Google Cloud Storage](https://cloud.google.com/storage/) (GCS). The bucket must exist prior to configuring the backend. This backend supports [state locking](https://opentofu.org/docs/v1.10/language/state/locking/) . Warning It is highly recommended that you enable [Object Versioning](https://cloud.google.com/storage/docs/object-versioning) on the GCS bucket to allow for state recovery in the case of accidental deletions and human error. Example Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#example-configuration "Direct link to Example Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block terraform { backend "gcs" { bucket = "tf-state-prod" prefix = "tofu/state" }} Data Source Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#data-source-configuration "Direct link to Data Source Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block data "terraform_remote_state" "foo" { backend = "gcs" config = { bucket = "tofu-state" prefix = "prod" }}resource "local_file" "foo" { content = data.terraform_remote_state.foo.outputs.greeting filename = "${path.module}/outputs.txt"} Authentication[​](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#authentication "Direct link to Authentication") ---------------------------------------------------------------------------------------------------------------------------------- IAM Changes to buckets are [eventually consistent](https://cloud.google.com/storage/docs/consistency#eventually_consistent_operations) and may take upto a few minutes to take effect. OpenTofu will return 403 errors till it is eventually consistent. ### Running OpenTofu on your workstation.[​](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#running-opentofu-on-your-workstation "Direct link to Running OpenTofu on your workstation.") If you are using OpenTofu on your workstation, you will need to install the Google Cloud SDK and authenticate using [User Application Default Credentials](https://cloud.google.com/sdk/gcloud/reference/auth/application-default) . User ADCs do [expire](https://developers.google.com/identity/protocols/oauth2#expiration) and you can refresh them by running `gcloud auth application-default login`. ### Running OpenTofu on Google Cloud[​](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#running-opentofu-on-google-cloud "Direct link to Running OpenTofu on Google Cloud") If you are running OpenTofu on Google Cloud, you can configure that instance or cluster to use a [Google Service Account](https://cloud.google.com/compute/docs/authentication) . This will allow OpenTofu to authenticate to Google Cloud without having to bake in a separate credential/authentication file. Make sure that the scope of the VM/Cluster is set to cloud-platform. ### Running OpenTofu outside of Google Cloud[​](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#running-opentofu-outside-of-google-cloud "Direct link to Running OpenTofu outside of Google Cloud") If you are running OpenTofu outside of Google Cloud, generate a service account key and set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the path of the service account key. OpenTofu will use that key for authentication. ### Impersonating Service Accounts[​](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#impersonating-service-accounts "Direct link to Impersonating Service Accounts") OpenTofu can impersonate a Google Service Account as described [here](https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials) . A valid credential must be provided as mentioned in the earlier section and that identity must have the `roles/iam.serviceAccountTokenCreator` role on the service account you are impersonating. Encryption[​](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#encryption "Direct link to Encryption") ---------------------------------------------------------------------------------------------------------------------- Warning Take care of your encryption keys because state data encrypted with a lost or deleted key is not recoverable. If you use customer-supplied encryption keys, you must securely manage your keys and ensure you do not lose them. You must not delete customer-managed encryption keys in Cloud KMS used to encrypt state. However, if you accidentally delete a key, there is a time window where [you can recover it](https://cloud.google.com/kms/docs/destroy-restore#restore) . ### Customer-supplied encryption keys[​](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#customer-supplied-encryption-keys "Direct link to Customer-supplied encryption keys") To get started, follow this guide: [Use customer-supplied encryption keys](https://cloud.google.com/storage/docs/encryption/using-customer-supplied-keys) If you want to remove customer-supplied keys from your backend configuration or change to a different customer-supplied key, OpenTofu cannot perform a state migration automatically and manual intervention is necessary instead. This intervention is necessary because Google does not store customer-supplied encryption keys, any requests sent to the Cloud Storage API must supply them instead (see [Customer-supplied Encryption Keys](https://cloud.google.com/storage/docs/encryption/customer-supplied-keys) ). At the time of state migration, the backend configuration loses the old key's details and OpenTofu cannot use the key during the migration process. Important To migrate your state away from using customer-supplied encryption keys or change the key used by your backend, you need to perform a [rewrite (gsutil CLI)](https://cloud.google.com/storage/docs/gsutil/commands/rewrite) or [cp (gcloud CLI)](https://cloud.google.com/sdk/gcloud/reference/storage/cp#--decryption-keys) operation to remove use of the old customer-supplied encryption key on your state file. Once you remove the encryption, you can successfully run `tofu init -migrate-state` with your new backend configuration. ### Customer-managed encryption keys (Cloud KMS)[​](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#customer-managed-encryption-keys-cloud-kms "Direct link to Customer-managed encryption keys (Cloud KMS)") To get started, follow this guide: [Use customer-managed encryption keys](https://cloud.google.com/storage/docs/encryption/using-customer-managed-keys) If you want to remove customer-managed keys from your backend configuration or change to a different customer-managed key, OpenTofu _can_ manage a state migration without manual intervention. This ability is because GCP stores customer-managed encryption keys and are accessible during the state migration process. However, these changes do not fully come into effect until the first write operation occurs on the state file after state migration occurs. In the first write operation after state migration, the file decrypts with the old key and then writes with the new encryption method. This method is equivalent to the [rewrite](https://cloud.google.com/storage/docs/gsutil/commands/rewrite) operation described in the customer-supplied encryption keys section. Because of the importance of the first write to state after state migration, you should not delete old KMS keys until any state file(s) encrypted with that key update. Customer-managed keys do not need to be sent in requests to read files from GCS buckets because decryption occurs automatically within GCS. This process means that if you use the `terraform_remote_state` [data source](https://opentofu.org/docs/v1.10/language/state/remote-state-data/) to access KMS-encrypted state, you do not need to specify the KMS key in the data source's `config` object. Important To use customer-managed encryption keys, you need to create a key and give your project's GCS service agent permission to use it with the Cloud KMS CryptoKey Encrypter/Decrypter predefined role. Configuration Variables[​](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#configuration-variables "Direct link to Configuration Variables") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Warning We recommend using environment variables to supply credentials and other sensitive data. If you use `-backend-config` or hardcode these values directly in your configuration, OpenTofu includes these values in both the `.terraform` subdirectory and in plan files. Refer to [Credentials and Sensitive Data](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#credentials-and-sensitive-data) for details. The following configuration options are supported: * `bucket` - (Required) The name of the GCS bucket. This name must be globally unique. For more information, see [Bucket Naming Guidelines](https://cloud.google.com/storage/docs/bucketnaming.html#requirements) . * `credentials` / `GOOGLE_BACKEND_CREDENTIALS` / `GOOGLE_CREDENTIALS` - (Optional) Local path to Google Cloud Platform account credentials in JSON format. If unset, the path uses [Google Application Default Credentials](https://developers.google.com/identity/protocols/application-default-credentials) . The provided credentials must have the Storage Object Admin role on the bucket. **Warning**: if using the Google Cloud Platform provider as well, it will also pick up the `GOOGLE_CREDENTIALS` environment variable. * `impersonate_service_account` / `GOOGLE_BACKEND_IMPERSONATE_SERVICE_ACCOUNT` / `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` - (Optional) The service account to impersonate for accessing the State Bucket. You must have `roles/iam.serviceAccountTokenCreator` role on that account for the impersonation to succeed. If you are using a delegation chain, you can specify that using the `impersonate_service_account_delegates` field. * `impersonate_service_account_delegates` - (Optional) The delegation chain for an impersonating a service account as described [here](https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials#sa-credentials-delegated) . * `access_token` - (Optional) A temporary \[OAuth 2.0 access token\] obtained from the Google Authorization server, i.e. the `Authorization: Bearer` token used to authenticate HTTP requests to GCP APIs. This is an alternative to `credentials`. If both are specified, `access_token` will be used over the `credentials` field. * `prefix` - (Optional) GCS prefix inside the bucket. Named states for workspaces are stored in an object called `/.tfstate`. * `encryption_key` / `GOOGLE_ENCRYPTION_KEY` - (Optional) A 32 byte base64 encoded 'customer-supplied encryption key' used when reading and writing state files in the bucket. For more information see [Customer-supplied Encryption Keys](https://cloud.google.com/storage/docs/encryption/customer-supplied-keys) . * `kms_encryption_key` / `GOOGLE_KMS_ENCRYPTION_KEY` - (Optional) A Cloud KMS key ('customer-managed encryption key') used when reading and writing state files in the bucket. Format should be `projects/{{project}}/locations/{{location}}/keyRings/{{keyRing}}/cryptoKeys/{{name}}`. For more information, including IAM requirements, see [Customer-managed Encryption Keys](https://cloud.google.com/storage/docs/encryption/customer-managed-keys) . * `storage_custom_endpoint` / `GOOGLE_BACKEND_STORAGE_CUSTOM_ENDPOINT` / `GOOGLE_STORAGE_CUSTOM_ENDPOINT` - (Optional) A URL containing three parts: the protocol, the DNS name pointing to a Private Service Connect endpoint, and the path for the Cloud Storage API (`/storage/v1/b`, [see here](https://cloud.google.com/storage/docs/json_api/v1/buckets/get#http-request) ). You can either use [a DNS name automatically made by the Service Directory](https://cloud.google.com/vpc/docs/configure-private-service-connect-apis#configure-p-dns) or a [custom DNS name](https://cloud.google.com/vpc/docs/configure-private-service-connect-apis#configure-dns-default) made by you. For example, if you create an endpoint called `xyz` and want to use the automatically-created DNS name, you should set the field value as `https://storage-xyz.p.googleapis.com/storage/v1/b`. For help creating a Private Service Connect endpoint using OpenTofu, [see this guide](https://cloud.google.com/vpc/docs/configure-private-service-connect-apis#terraform_1) . * [Example Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#example-configuration) * [Data Source Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#data-source-configuration) * [Authentication](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#authentication) * [Running OpenTofu on your workstation.](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#running-opentofu-on-your-workstation) * [Running OpenTofu on Google Cloud](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#running-opentofu-on-google-cloud) * [Running OpenTofu outside of Google Cloud](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#running-opentofu-outside-of-google-cloud) * [Impersonating Service Accounts](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#impersonating-service-accounts) * [Encryption](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#encryption) * [Customer-supplied encryption keys](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#customer-supplied-encryption-keys) * [Customer-managed encryption keys (Cloud KMS)](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#customer-managed-encryption-keys-cloud-kms) * [Configuration Variables](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/#configuration-variables) --- # Backend Type: oss | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/backends/oss/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Backend Type: oss ================= Stores the state as a given key in a given bucket on Stores [Alibaba Cloud OSS](https://www.alibabacloud.com/help/product/31815.htm) . This backend also supports state locking and consistency checking via [Alibaba Cloud Table Store](https://www.alibabacloud.com/help/doc-detail/27280.htm) , which can be enabled by setting the `tablestore_table` field to an existing TableStore table name. This backend supports [state locking](https://opentofu.org/docs/v1.10/language/state/locking/) via TableStore. Example Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/oss/#example-configuration "Direct link to Example Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block terraform { backend "oss" { bucket = "bucket-for-tofu-state" prefix = "path/mystate" key = "version-1.tfstate" region = "cn-beijing" tablestore_endpoint = "https://tofu-remote.cn-hangzhou.ots.aliyuncs.com" tablestore_table = "statelock" }} This assumes we have a [OSS Bucket](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/oss_bucket) created called `bucket-for-tofu-state`, a [OTS Instance](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/ots_instance) called `tofu-remote` and a [OTS TableStore](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/ots_table) called `statelock`. The OpenTofu state will be written into the file `path/mystate/version-1.tfstate`. The `TableStore` must have a primary key named `LockID` of type `String`. Data Source Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/oss/#data-source-configuration "Direct link to Data Source Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- To make use of the OSS remote state in another configuration, use the [`terraform_remote_state` data source](https://opentofu.org/docs/v1.10/language/state/remote-state-data/) . Code Block terraform { backend "oss" { bucket = "remote-state-dns" prefix = "mystate/state" key = "terraform.tfstate" region = "cn-beijing" }} The `terraform_remote_state` data source will return all of the root outputs defined in the referenced remote state, an example output might look like: Code Block data "terraform_remote_state" "network" { backend = "oss" config = { bucket = "remote-state-dns" key = "terraform.tfstate" prefix = "mystate/state" region = "cn-beijing" } outputs = {} workspace = "default"} Configuration Variables[​](https://opentofu.org/docs/v1.10/language/settings/backends/oss/#configuration-variables "Direct link to Configuration Variables") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Warning We recommend using environment variables to supply credentials and other sensitive data. If you use `-backend-config` or hardcode these values directly in your configuration, OpenTofu will include these values in both the `.terraform` subdirectory and in plan files. Refer to [Credentials and Sensitive Data](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#credentials-and-sensitive-data) for details. The following configuration options or environment variables are supported: * `access_key` - (Optional) Alibaba Cloud access key. It supports environment variables `ALICLOUD_ACCESS_KEY` and `ALICLOUD_ACCESS_KEY_ID`. * `secret_key` - (Optional) Alibaba Cloud secret access key. It supports environment variables `ALICLOUD_SECRET_KEY` and `ALICLOUD_ACCESS_KEY_SECRET`. * `security_token` - (Optional) STS access token. It supports environment variable `ALICLOUD_SECURITY_TOKEN`. * `ecs_role_name` - (Optional, Available in 0.12.14+) The RAM Role Name attached on a ECS instance for API operations. You can retrieve this from the 'Access Control' section of the Alibaba Cloud console. * `region` - (Optional) The region of the OSS bucket. It supports environment variables `ALICLOUD_REGION` and `ALICLOUD_DEFAULT_REGION`. * `endpoint` - (Optional) A custom endpoint for the OSS API. It supports environment variables `ALICLOUD_OSS_ENDPOINT` and `OSS_ENDPOINT`. * `bucket` - (Required) The name of the OSS bucket. * `prefix` - (Opeional) The path directory of the state file will be stored. Default to "env:". * `key` - (Optional) The name of the state file. Defaults to `terraform.tfstate`. * `tablestore_endpoint` / `ALICLOUD_TABLESTORE_ENDPOINT` - (Optional) A custom endpoint for the TableStore API. * `tablestore_table` - (Optional) A TableStore table for state locking and consistency. The table must have a primary key named `LockID` of type `String`. * `sts_endpoint` - (Optional, Available in 1.0.11+) Custom endpoint for the AliCloud Security Token Service (STS) API. It supports environment variable `ALICLOUD_STS_ENDPOINT`. * `encrypt` - (Optional) Whether to enable server side encryption of the state file. If it is true, OSS will use 'AES256' encryption algorithm to encrypt state file. * `acl` - (Optional) [Object ACL](https://www.alibabacloud.com/help/doc-detail/52284.htm) to be applied to the state file. * `shared_credentials_file` - (Optional, Available in 0.12.8+) This is the path to the shared credentials file. It can also be sourced from the `ALICLOUD_SHARED_CREDENTIALS_FILE` environment variable. If this is not set and a profile is specified, `~/.aliyun/config.json` will be used. * `profile` - (Optional, Available in 0.12.8+) This is the Alibaba Cloud profile name as set in the shared credentials file. It can also be sourced from the `ALICLOUD_PROFILE` environment variable. * `assume_role_role_arn` - (Optional, Available in 1.1.0+) The ARN of the role to assume. If ARN is set to an empty string, it does not perform role switching. It supports the environment variable `ALICLOUD_ASSUME_ROLE_ARN`. OpenTofu executes configuration on account with provided credentials. * `assume_role_policy` - (Optional, Available in 1.1.0+) A more restrictive policy to apply to the temporary credentials. This gives you a way to further restrict the permissions for the resulting temporary security credentials. You cannot use this policy to grant permissions that exceed those of the role that is being assumed. * `assume_role_session_name` - (Optional, Available in 1.1.0+) The session name to use when assuming the role. If omitted, 'tofu' is passed to the AssumeRole call as session name. It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_NAME`. * `assume_role_session_expiration` - (Optional, Available in 1.1.0+) The time after which the established session for assuming role expires. Valid value range: \[900-3600\] seconds. Default to 3600 (in this case Alibaba Cloud uses its own default value). It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION`. * `assume_role` - (**Deprecated as of 1.1.0+**, Available in 0.12.6+) If provided with a role ARN, will attempt to assume this role using the supplied credentials. It will be ignored when `assume_role_role_arn` is specified. **Deprecated in favor of flattening assume\_role\_\* options** * `role_arn` - (Required) The ARN of the role to assume. If ARN is set to an empty string, it does not perform role switching. It supports the environment variable `ALICLOUD_ASSUME_ROLE_ARN`. OpenTofu executes configuration on account with provided credentials. * `policy` - (Optional) A more restrictive policy to apply to the temporary credentials. This gives you a way to further restrict the permissions for the resulting temporary security credentials. You cannot use this policy to grant permissions that exceed those of the role that is being assumed. * `session_name` - (Optional) The session name to use when assuming the role. If omitted, 'tofu' is passed to the AssumeRole call as session name. It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_NAME`. * `session_expiration` - (Optional) The time after which the established session for assuming role expires. Valid value range: \[900-3600\] seconds. Default to 3600 (in this case Alibaba Cloud uses its own default value). It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION`. Note If you want to store state in the custom OSS endpoint, you can specify an environment variable `OSS_ENDPOINT`, like "oss-cn-beijing-internal.aliyuncs.com" * [Example Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/oss/#example-configuration) * [Data Source Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/oss/#data-source-configuration) * [Configuration Variables](https://opentofu.org/docs/v1.10/language/settings/backends/oss/#configuration-variables) --- # Module Composition | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/modules/develop/composition/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Module Composition ================== In a simple OpenTofu configuration with only one root module, we create a flat set of resources and use OpenTofu's expression syntax to describe the relationships between these resources: Code Block resource "aws_vpc" "example" { cidr_block = "10.1.0.0/16"}resource "aws_subnet" "example" { vpc_id = aws_vpc.example.id availability_zone = "us-west-2b" cidr_block = cidrsubnet(aws_vpc.example.cidr_block, 4, 1)} When we introduce `module` blocks, our configuration becomes hierarchical rather than flat: each module contains its own set of resources, and possibly its own child modules, which can potentially create a deep, complex tree of resource configurations. However, in most cases we strongly recommend keeping the module tree flat, with only one level of child modules, and use a technique similar to the above of using expressions to describe the relationships between the modules: Code Block module "network" { source = "./modules/aws-network" base_cidr_block = "10.0.0.0/8"}module "consul_cluster" { source = "./modules/aws-consul-cluster" vpc_id = module.network.vpc_id subnet_ids = module.network.subnet_ids} We call this flat style of module usage _module composition_, because it takes multiple [composable](https://en.wikipedia.org/wiki/Composability) building-block modules and assembles them together to produce a larger system. Instead of a module _embedding_ its dependencies, creating and managing its own copy, the module _receives_ its dependencies from the root module, which can therefore connect the same modules in different ways to produce different results. The rest of this page discusses some more specific composition patterns that may be useful when describing larger systems with OpenTofu. Dependency Inversion[​](https://opentofu.org/docs/v1.10/language/modules/develop/composition/#dependency-inversion "Direct link to Dependency Inversion") ---------------------------------------------------------------------------------------------------------------------------------------------------------- In the example above, we saw a `consul_cluster` module that presumably describes a cluster of [HashiCorp Consul](https://www.consul.io/) servers running in an AWS VPC network, and thus it requires as arguments the identifiers of both the VPC itself and of the subnets within that VPC. An alternative design would be to have the `consul_cluster` module describe its _own_ network resources, but if we did that then it would be hard for the Consul cluster to coexist with other infrastructure in the same network, and so where possible we prefer to keep modules relatively small and pass in their dependencies. This [dependency inversion](https://en.wikipedia.org/wiki/Dependency_inversion_principle) approach also improves flexibility for future refactoring, because the `consul_cluster` module doesn't know or care how those identifiers are obtained by the calling module. A future refactor may separate the network creation into its own configuration, and thus we may pass those values into the module from data sources instead: Code Block data "aws_vpc" "main" { tags = { Environment = "production" }}data "aws_subnet_ids" "main" { vpc_id = data.aws_vpc.main.id}module "consul_cluster" { source = "./modules/aws-consul-cluster" vpc_id = data.aws_vpc.main.id subnet_ids = data.aws_subnet_ids.main.ids} ### Conditional Creation of Objects[​](https://opentofu.org/docs/v1.10/language/modules/develop/composition/#conditional-creation-of-objects "Direct link to Conditional Creation of Objects") In situations where the same module is used across multiple environments, it's common to see that some necessary object already exists in some environments but needs to be created in other environments. For example, this can arise in development environment scenarios: for cost reasons, certain infrastructure may be shared across multiple development environments, while in production the infrastructure is unique and managed directly by the production configuration. Rather than trying to write a module that itself tries to detect whether something exists and create it if not, we recommend applying the dependency inversion approach: making the module accept the object it needs as an argument, via an input variable. For example, consider a situation where an OpenTofu module deploys compute instances based on a disk image, and in some environments there is a specialized disk image available while other environments share a common base disk image. Rather than having the module itself handle both of these scenarios, we can instead declare an input variable for an object representing the disk image. Using AWS EC2 as an example, we might declare a common subtype of the `aws_ami` resource type and data source schemas: Code Block variable "ami" { type = object({ # Declare an object using only the subset of attributes the module # needs. OpenTofu will allow any object that has at least these # attributes. id = string architecture = string })} The caller of this module can now itself directly represent whether this is an AMI to be created inline or an AMI to be retrieved from elsewhere: Code Block # In situations where the AMI will be directly managed:resource "aws_ami_copy" "example" { name = "local-copy-of-ami" source_ami_id = "ami-abc123" source_ami_region = "eu-west-1"}module "example" { source = "./modules/example" ami = aws_ami_copy.example} Code Block # Or, in situations where the AMI already exists:data "aws_ami" "example" { owner = "9999933333" tags = { application = "example-app" environment = "dev" }}module "example" { source = "./modules/example" ami = data.aws_ami.example} This is consistent with OpenTofu's declarative style: rather than creating modules with complex conditional branches, we directly describe what should already exist and what we want OpenTofu to manage itself. By following this pattern, we can be explicit about in which situations we expect the AMI to already be present and which we don't. A future reader of the configuration can then directly understand what it is intending to do without first needing to inspect the state of the remote system. In the above example, the object to be created or read is simple enough to be given inline as a single resource, but we can also compose together multiple modules as described elsewhere on this page in situations where the dependencies themselves are complicated enough to benefit from abstractions. Assumptions and Guarantees[​](https://opentofu.org/docs/v1.10/language/modules/develop/composition/#assumptions-and-guarantees "Direct link to Assumptions and Guarantees") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Every module has implicit assumptions and guarantees that define what data it expects and what data it produces for consumers. * **Assumption:** A condition that must be true in order for the configuration of a particular resource to be usable. For example, an `aws_instance` configuration can have the assumption that the given AMI will always be configured for the `x86_64` CPU architecture. * **Guarantee:** A characteristic or behavior of an object that the rest of the configuration should be able to rely on. For example, an `aws_instance` configuration can have the guarantee that an EC2 instance will be running in a network that assigns it a private DNS record. We recommend using [custom conditions](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/) to help capture and test for assumptions and guarantees. This helps future maintainers understand the configuration design and intent. Custom conditions also return useful information about errors earlier and in context, helping consumers more easily diagnose issues in their configurations. The following examples creates a precondition that checks whether the EC2 instance has an encrypted root volume. Code Block output "api_base_url" { value = "https://${aws_instance.example.private_dns}:8433/" # The EC2 instance must have an encrypted root volume. precondition { condition = data.aws_ebs_volume.example.encrypted error_message = "The server's root volume is not encrypted." }} Multi-cloud Abstractions[​](https://opentofu.org/docs/v1.10/language/modules/develop/composition/#multi-cloud-abstractions "Direct link to Multi-cloud Abstractions") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu itself intentionally does not attempt to abstract over similar services offered by different vendors, because we want to expose the full functionality in each offering and yet unifying multiple offerings behind a single interface will tend to require a "lowest common denominator" approach. However, through composition of modules it is possible to create your own lightweight multi-cloud abstractions by making your own tradeoffs about which platform features are important to you. Opportunities for such abstractions arise in any situation where multiple vendors implement the same concept, protocol, or open standard. For example, the basic capabilities of the domain name system are common across all vendors, and although some vendors differentiate themselves with unique features such as geolocation and smart load balancing, you may conclude that in your use-case you are willing to eschew those features in return for creating modules that abstract the common DNS concepts across multiple vendors: Code Block module "webserver" { source = "./modules/webserver"}locals { fixed_recordsets = [ { name = "www" type = "CNAME" ttl = 3600 records = [ "webserver01", "webserver02", "webserver03", ] }, ] server_recordsets = [ for i, addr in module.webserver.public_ip_addrs : { name = format("webserver%02d", i) type = "A" records = [addr] } ]}module "dns_records" { source = "./modules/route53-dns-records" route53_zone_id = var.route53_zone_id recordsets = concat(local.fixed_recordsets, local.server_recordsets)} In the above example, we've created a lightweight abstraction in the form of a "recordset" object. This contains the attributes that describe the general idea of a DNS recordset that should be mappable onto any DNS provider. We then instantiate one specific _implementation_ of that abstraction as a module, in this case deploying our recordsets to Amazon Route53. If we later wanted to switch to a different DNS provider, we'd need only to replace the `dns_records` module with a new implementation targeting that provider, and all of the configuration that _produces_ the recordset definitions can remain unchanged. We can create lightweight abstractions like these by defining OpenTofu object types representing the concepts involved and then using these object types for module input variables. In this case, all of our "DNS records" implementations would have the following variable declared: Code Block variable "recordsets" { type = list(object({ name = string type = string ttl = number records = list(string) }))} While DNS serves as a simple example, there are many more opportunities to exploit common elements across vendors. A more complex example is Kubernetes, where there are now many different vendors offering hosted Kubernetes clusters and even more ways to run Kubernetes yourself. If the common functionality across all of these implementations is sufficient for your needs, you may choose to implement a set of different modules that describe a particular Kubernetes cluster implementation and all have the common trait of exporting the hostname of the cluster as an output value: Code Block output "hostname" { value = azurerm_kubernetes_cluster.main.fqdn} You can then write _other_ modules that expect only a Kubernetes cluster hostname as input and use them interchangeably with any of your Kubernetes cluster modules: Code Block module "k8s_cluster" { source = "modules/azurerm-k8s-cluster" # (Azure-specific configuration arguments)}module "monitoring_tools" { source = "modules/monitoring_tools" cluster_hostname = module.k8s_cluster.hostname} Data-only Modules[​](https://opentofu.org/docs/v1.10/language/modules/develop/composition/#data-only-modules "Direct link to Data-only Modules") ------------------------------------------------------------------------------------------------------------------------------------------------- Most modules contain `resource` blocks and thus describe infrastructure to be created and managed. It may sometimes be useful to write modules that do not describe any new infrastructure at all, but merely retrieve information about existing infrastructure that was created elsewhere using [data sources](https://opentofu.org/docs/v1.10/language/data-sources/) . As with conventional modules, we suggest using this technique only when the module raises the level of abstraction in some way, in this case by encapsulating exactly how the data is retrieved. A common use of this technique is when a system has been decomposed into several subsystem configurations but there is certain infrastructure that is shared across all of the subsystems, such as a common IP network. In this situation, we might write a shared module called `join-network-aws` which can be called by any configuration that needs information about the shared network when deployed in AWS: Code Block module "network" { source = "./modules/join-network-aws" environment = "production"}module "k8s_cluster" { source = "./modules/aws-k8s-cluster" subnet_ids = module.network.aws_subnet_ids} The `network` module itself could retrieve this data in a number of different ways: it could query the AWS API directly using [`aws_vpc`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) and [`aws_subnet_ids`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnet_ids) data sources, or it could read saved information from a Consul cluster using [`consul_keys`](https://registry.terraform.io/providers/hashicorp/consul/latest/docs/data-sources/keys) , or it might read the outputs directly from the state of the configuration that manages the network using [`terraform_remote_state`](https://opentofu.org/docs/v1.10/language/state/remote-state-data/) . The key benefit of this approach is that the source of this information can change over time without updating every configuration that depends on it. Furthermore, if you design your data-only module with a similar set of outputs as a corresponding management module, you can swap between the two relatively easily when refactoring. * [Dependency Inversion](https://opentofu.org/docs/v1.10/language/modules/develop/composition/#dependency-inversion) * [Conditional Creation of Objects](https://opentofu.org/docs/v1.10/language/modules/develop/composition/#conditional-creation-of-objects) * [Assumptions and Guarantees](https://opentofu.org/docs/v1.10/language/modules/develop/composition/#assumptions-and-guarantees) * [Multi-cloud Abstractions](https://opentofu.org/docs/v1.10/language/modules/develop/composition/#multi-cloud-abstractions) * [Data-only Modules](https://opentofu.org/docs/v1.10/language/modules/develop/composition/#data-only-modules) --- # Backend Type: azurerm | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/backends/azurerm/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Backend Type: azurerm ===================== Stores the state as a Blob with the given Key within the Blob Container within [the Blob Storage Account](https://docs.microsoft.com/en-us/azure/storage/common/storage-introduction) . This backend supports state locking and consistency checking with Azure Blob Storage native capabilities. Example Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/azurerm/#example-configuration "Direct link to Example Configuration") ----------------------------------------------------------------------------------------------------------------------------------------------------------- When authenticating using the Azure CLI or a Service Principal (either with a Client Certificate or a Client Secret): Code Block terraform { backend "azurerm" { resource_group_name = "StorageAccount-ResourceGroup" storage_account_name = "abcd1234" container_name = "tfstate" key = "prod.terraform.tfstate" }} * * * When authenticating using Managed Service Identity (MSI): Code Block terraform { backend "azurerm" { resource_group_name = "StorageAccount-ResourceGroup" storage_account_name = "abcd1234" container_name = "tfstate" key = "prod.terraform.tfstate" use_msi = true subscription_id = "00000000-0000-0000-0000-000000000000" tenant_id = "00000000-0000-0000-0000-000000000000" }} * * * When authenticating using OpenID Connect (OIDC): Code Block terraform { backend "azurerm" { resource_group_name = "StorageAccount-ResourceGroup" storage_account_name = "abcd1234" container_name = "tfstate" key = "prod.terraform.tfstate" use_oidc = true subscription_id = "00000000-0000-0000-0000-000000000000" tenant_id = "00000000-0000-0000-0000-000000000000" }} * * * When authenticating using Azure AD Authentication: Code Block terraform { backend "azurerm" { storage_account_name = "abcd1234" container_name = "tfstate" key = "prod.terraform.tfstate" use_azuread_auth = true subscription_id = "00000000-0000-0000-0000-000000000000" tenant_id = "00000000-0000-0000-0000-000000000000" }} Note When using AzureAD for Authentication to Storage you also need to ensure the `Storage Blob Data Owner` role is assigned. * * * When authenticating using the Access Key associated with the Storage Account: Code Block terraform { backend "azurerm" { storage_account_name = "abcd1234" container_name = "tfstate" key = "prod.terraform.tfstate" # rather than defining this inline, the Access Key can also be sourced # from an Environment Variable - more information is available below. access_key = "abcdefghijklmnopqrstuvwxyz0123456789..." }} * * * When authenticating using a SAS Token associated with the Storage Account: Code Block terraform { backend "azurerm" { storage_account_name = "abcd1234" container_name = "tfstate" key = "prod.terraform.tfstate" # rather than defining this inline, the SAS Token can also be sourced # from an Environment Variable - more information is available below. sas_token = "abcdefghijklmnopqrstuvwxyz0123456789..." }} Note When using a Service Principal or an Access Key - we recommend using a [Partial Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#partial-configuration) for the credentials. Data Source Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/azurerm/#data-source-configuration "Direct link to Data Source Configuration") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- When authenticating using a Service Principal (either with a Client Certificate or a Client Secret): Code Block data "terraform_remote_state" "foo" { backend = "azurerm" config = { storage_account_name = "tofu123abc" container_name = "tofu-state" key = "prod.terraform.tfstate" }} * * * When authenticating using Managed Service Identity (MSI): Code Block data "terraform_remote_state" "foo" { backend = "azurerm" config = { resource_group_name = "StorageAccount-ResourceGroup" storage_account_name = "tofu123abc" container_name = "tofu-state" key = "prod.terraform.tfstate" use_msi = true subscription_id = "00000000-0000-0000-0000-000000000000" tenant_id = "00000000-0000-0000-0000-000000000000" }} * * * When authenticating using OpenID Connect (OIDC): Code Block data "terraform_remote_state" "foo" { backend = "azurerm" config = { resource_group_name = "StorageAccount-ResourceGroup" storage_account_name = "tofu123abc" container_name = "tofu-state" key = "prod.terraform.tfstate" use_oidc = true subscription_id = "00000000-0000-0000-0000-000000000000" tenant_id = "00000000-0000-0000-0000-000000000000" }} * * * When authenticating using AzureAD Authentication: Code Block data "terraform_remote_state" "foo" { backend = "azurerm" config = { storage_account_name = "tofu123abc" container_name = "tofu-state" key = "prod.terraform.tfstate" use_azuread_auth = true subscription_id = "00000000-0000-0000-0000-000000000000" tenant_id = "00000000-0000-0000-0000-000000000000" }} Note When using AzureAD for Authentication to Storage you also need to ensure the `Storage Blob Data Owner` role is assigned. * * * When authenticating using the Access Key associated with the Storage Account: Code Block data "terraform_remote_state" "foo" { backend = "azurerm" config = { storage_account_name = "tofu123abc" container_name = "tofu-state" key = "prod.terraform.tfstate" # rather than defining this inline, the Access Key can also be sourced # from an Environment Variable - more information is available below. access_key = "abcdefghijklmnopqrstuvwxyz0123456789..." }} * * * When authenticating using a SAS Token associated with the Storage Account: Code Block data "terraform_remote_state" "foo" { backend = "azurerm" config = { storage_account_name = "tofu123abc" container_name = "tofu-state" key = "prod.terraform.tfstate" # rather than defining this inline, the SAS Token can also be sourced # from an Environment Variable - more information is available below. sas_token = "abcdefghijklmnopqrstuvwxyz0123456789..." }} Configuration Variables[​](https://opentofu.org/docs/v1.10/language/settings/backends/azurerm/#configuration-variables "Direct link to Configuration Variables") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- Warning We recommend using environment variables to supply credentials and other sensitive data. If you use `-backend-config` or hardcode these values directly in your configuration, OpenTofu will include these values in both the `.terraform` subdirectory and in plan files. Refer to [Credentials and Sensitive Data](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#credentials-and-sensitive-data) for details. The following configuration options are supported: * `storage_account_name` - (Required) The Name of [the Storage Account](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account) . * `container_name` - (Required) The Name of [the Storage Container](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_container) within the Storage Account. * `key` - (Required) The name of the Blob used to retrieve/store OpenTofu's State file inside the Storage Container. * `environment` - (Optional) The Azure Environment which should be used. This can also be sourced from the `ARM_ENVIRONMENT` environment variable. Possible values are `public`, `china`, `german`, `stack` and `usgovernment`. Defaults to `public`. * `endpoint` - (Optional) The Custom Endpoint for Azure Resource Manager. This can also be sourced from the `ARM_ENDPOINT` environment variable. Note An `endpoint` should only be configured when using Azure Stack. * `timeout_seconds` - (Optional) The number of seconds before a timeout is reached when attempting to initialize a client, retrieve a Blob or a Metadata from Azure. This can also be sourced from the `ARM_TIMEOUT_SECONDS` environment variable. Defaults to `300` (5 minutes). To disable the timeout, set this to `0`. Note Setting `timeout_seconds` to `0` or a large value only disables/extends timeouts originating from OpenTofu. Requests will still time out based on your system's network configuration. * `metadata_host` - (Optional) The Hostname of the Azure Metadata Service (for example `management.azure.com`), used to obtain the Cloud Environment when using a Custom Azure Environment. This can also be sourced from the `ARM_METADATA_HOSTNAME` Environment Variable. * `snapshot` - (Optional) Should the Blob used to store the OpenTofu Statefile be snapshotted before use? Defaults to `false`. This value can also be sourced from the `ARM_SNAPSHOT` environment variable. * * * When authenticating using the Managed Service Identity (MSI) - the following fields are also supported: * `resource_group_name` - (Required) The Name of the Resource Group in which the Storage Account exists. * `msi_endpoint` - (Optional) The path to a custom Managed Service Identity endpoint which is automatically determined if not specified. This can also be sourced from the `ARM_MSI_ENDPOINT` environment variable. * `subscription_id` - (Optional) The Subscription ID in which the Storage Account exists. This can also be sourced from the `ARM_SUBSCRIPTION_ID` environment variable. * `tenant_id` - (Optional) The Tenant ID in which the Subscription exists. This can also be sourced from the `ARM_TENANT_ID` environment variable. * `use_msi` - (Optional) Should Managed Service Identity authentication be used? This can also be sourced from the `ARM_USE_MSI` environment variable. * * * When authenticating using a Service Principal with OpenID Connect (OIDC) - the following fields are also supported: * `oidc_request_url` - (Optional) The URL for the OIDC provider from which to request an ID token. This can also be sourced from the `ARM_OIDC_REQUEST_URL` or `ACTIONS_ID_TOKEN_REQUEST_URL` environment variables. * `oidc_request_token` - (Optional) The bearer token for the request to the OIDC provider. This can also be sourced from the `ARM_OIDC_REQUEST_TOKEN` or `ACTIONS_ID_TOKEN_REQUEST_TOKEN` environment variables. * `oidc_token` - (Optional) The ID token when authenticating using OpenID Connect (OIDC). This can also be sourced from the `ARM_OIDC_TOKEN` environment variable. * `oidc_token_file_path` - (Optional) The path to a file containing an ID token when authenticating using OpenID Connect (OIDC). This can also be sourced from the `ARM_OIDC_TOKEN_FILE_PATH` environment variable. * `use_oidc` - (Optional) Should OIDC authentication be used? This can also be sourced from the `ARM_USE_OIDC` environment variable. * * * When authenticating using a SAS Token associated with the Storage Account - the following fields are also supported: * `sas_token` - (Optional) The SAS Token used to access the Blob Storage Account. This can also be sourced from the `ARM_SAS_TOKEN` environment variable. * * * When authenticating using the Storage Account's Access Key - the following fields are also supported: * `access_key` - (Optional) The Access Key used to access the Blob Storage Account. This can also be sourced from the `ARM_ACCESS_KEY` environment variable. * * * When authenticating using AzureAD Authentication - the following fields are also supported: * `use_azuread_auth` - (Optional) Should AzureAD Authentication be used to access the Blob Storage Account. This can also be sourced from the `ARM_USE_AZUREAD` environment variable. Note When using AzureAD for Authentication to Storage you also need to ensure the `Storage Blob Data Owner` role is assigned. * * * When authenticating using a Service Principal with a Client Certificate - the following fields are also supported: * `resource_group_name` - (Required) The Name of the Resource Group in which the Storage Account exists. * `client_id` - (Optional) The Client ID of the Service Principal. This can also be sourced from the `ARM_CLIENT_ID` environment variable. * `client_certificate_password` - (Optional) The password associated with the Client Certificate specified in `client_certificate_path`. This can also be sourced from the `ARM_CLIENT_CERTIFICATE_PASSWORD` environment variable. * `client_certificate_path` - (Optional) The path to the PFX file used as the Client Certificate when authenticating as a Service Principal. This can also be sourced from the `ARM_CLIENT_CERTIFICATE_PATH` environment variable. * `subscription_id` - (Optional) The Subscription ID in which the Storage Account exists. This can also be sourced from the `ARM_SUBSCRIPTION_ID` environment variable. * `tenant_id` - (Optional) The Tenant ID in which the Subscription exists. This can also be sourced from the `ARM_TENANT_ID` environment variable. * * * When authenticating using a Service Principal with a Client Secret - the following fields are also supported: * `resource_group_name` - (Required) The Name of the Resource Group in which the Storage Account exists. * `client_id` - (Optional) The Client ID of the Service Principal. This can also be sourced from the `ARM_CLIENT_ID` environment variable. * `client_secret` - (Optional) The Client Secret of the Service Principal. This can also be sourced from the `ARM_CLIENT_SECRET` environment variable. * `subscription_id` - (Optional) The Subscription ID in which the Storage Account exists. This can also be sourced from the `ARM_SUBSCRIPTION_ID` environment variable. * `tenant_id` - (Optional) The Tenant ID in which the Subscription exists. This can also be sourced from the `ARM_TENANT_ID` environment variable. * [Example Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/azurerm/#example-configuration) * [Data Source Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/azurerm/#data-source-configuration) * [Configuration Variables](https://opentofu.org/docs/v1.10/language/settings/backends/azurerm/#configuration-variables) --- # What are TACOS? | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/tacos/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) What are TACOS? =============== TF Automation and Collaboration Software (TACOS) are platforms which allow teams to manage and orchestrate OpenTofu execution. They offer a wide variety of services to provide a streamlined and collaborative experience. What are some examples? ======================= There are a variety of platforms which offer OpenTofu support, both Open Source and Commercial. Many of these organizations support OpenTofu directly and can be found on our [supporters](https://opentofu.org/supporters/) page. --- # CLI Configuration | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/config/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) CLI Configuration ================= OpenTofu CLI can be configured with some global settings, which are separate from any OpenTofu configuration and which apply across all working directories. We've designed OpenTofu such that an average user running OpenTofu CLI interactively will not need to interact with any of these settings. As a result, most of the global settings relate to advanced or automated workflows, or unusual environmental conditions like running OpenTofu on an airgapped instance. * The [CLI config file](https://opentofu.org/docs/v1.11/cli/config/config-file/) configures provider installation and security features. * Several [environment variables](https://opentofu.org/docs/v1.11/cli/config/environment-variables/) can configure OpenTofu's inputs and outputs; this includes some alternate ways to provide information that is usually passed on the command line or read from the state of the shell. --- # Backend Configuration | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Backend Configuration ===================== A backend defines where OpenTofu stores its [state](https://opentofu.org/docs/v1.10/language/state/) data files. OpenTofu uses persisted state data to keep track of the resources it manages. Most non-trivial OpenTofu configurations either integrate with [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software) or use a backend to store state remotely. This lets multiple people access the state data and work together on that collection of infrastructure resources. This page describes how to configure a backend by adding the [`backend` block](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#using-a-backend-block) to your configuration. Available Backends[​](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#available-backends "Direct link to Available Backends") -------------------------------------------------------------------------------------------------------------------------------------------------------- By default, OpenTofu uses a backend called [`local`](https://opentofu.org/docs/v1.10/language/settings/backends/local/) , which stores state as a local file on disk. You can also configure one of the built-in backends included in this documentation. Some of these backends act like plain remote disks for state files, while others support locking the state while operations are being performed. This helps prevent conflicts and inconsistencies. The built-in backends listed are the only backends. You cannot load additional backends as plugins. Using a Backend Block[​](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#using-a-backend-block "Direct link to Using a Backend Block") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- You do not need to configure a backend when using [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software) because it automatically manages state in the workspaces associated with your configuration. If your configuration includes a [`cloud` block](https://opentofu.org/docs/v1.10/language/settings/tf-cloud/) , it cannot include a `backend` block. To configure a backend, add a nested `backend` block within the top-level `terraform` block. The following example configures the `remote` backend. Code Block terraform { backend "remote" { organization = "example_corp" workspaces { name = "my-app-prod" } }} There are some important limitations on backend configuration: * A configuration can only provide one backend block. * A backend block cannot refer to values in the state or locals derived from the state (data source attributes). ### Credentials and Sensitive Data[​](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#credentials-and-sensitive-data "Direct link to Credentials and Sensitive Data") Backends store state in a remote service, which allows multiple people to access it. Accessing remote state generally requires access credentials, since state data contains extremely sensitive information. Warning We recommend using environment variables to supply credentials and other sensitive data. If you use `-backend-config` or hardcode these values directly in your configuration, OpenTofu will include these values in both the `.terraform` subdirectory and in plan files. This can leak sensitive credentials. OpenTofu writes the backend configuration in plain text in two separate files. * The `.terraform/terraform.tfstate` file contains the backend configuration for the current working directory. * All plan files capture the information in `.terraform/terraform.tfstate` at the time the plan was created. This helps ensure OpenTofu is applying the plan to correct set of infrastructure. When applying a plan that you previously saved to a file, OpenTofu uses the backend configuration stored in that file instead of the current backend settings. If that configuration contains time-limited credentials, they may expire before you finish applying the plan. Use environment variables to pass credentials when you need to use different values between the plan and apply steps. ### Backend Types[​](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#backend-types "Direct link to Backend Types") The block label of the backend block (`"remote"`, in the example above) indicates which backend type to use. OpenTofu has a built-in selection of backends, and the configured backend must be available in the version of OpenTofu you are using. The arguments used in the block's body are specific to the chosen backend type; they configure where and how the backend will store the configuration's state, and in some cases configure other behavior. Some backends allow providing access credentials directly as part of the configuration for use in unusual situations, for pragmatic reasons. However, in normal use, we _do not_ recommend including access credentials as part of the backend configuration. Instead, leave those arguments completely unset and provide credentials using the credentials files or environment variables that are conventional for the target system, as described in the documentation for each backend. Refer to the page for each backend type for full details and that type's configuration arguments. ### Default Backend[​](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#default-backend "Direct link to Default Backend") If a configuration includes no backend block, OpenTofu defaults to using the `local` backend, which stores state as a plain file in the current working directory. Initialization[​](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#initialization "Direct link to Initialization") -------------------------------------------------------------------------------------------------------------------------------------------- When you change a backend's configuration, you must run `tofu init` again to validate and configure the backend before you can perform any plans, applies, or state operations. After you initialize, OpenTofu creates a `.terraform/` directory locally. This directory contains the most recent backend configuration, including any authentication parameters you provided to the OpenTofu CLI. Do not check this directory into Git, as it may contain sensitive credentials for your remote backend. The local backend configuration is different and entirely separate from the `terraform.tfstate` file that contains [state data](https://opentofu.org/docs/v1.10/language/state/) about your real-world infrastructure. OpenTofu stores the `terraform.tfstate` file in your remote backend. When you change backends, OpenTofu gives you the option to migrate your state to the new backend. This lets you adopt backends without losing any existing state. Important Before migrating to a new backend, we strongly recommend manually backing up your state by copying your `terraform.tfstate` file to another location. Partial Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#partial-configuration "Direct link to Partial Configuration") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- You do not need to specify every required argument in the backend configuration. Omitting certain arguments may be desirable if some arguments are provided automatically by an automation script running OpenTofu. When some or all of the arguments are omitted, we call this a _partial configuration_. With a partial configuration, the remaining configuration arguments must be provided as part of [the initialization process](https://opentofu.org/docs/v1.10/cli/init/) . There are several ways to supply the remaining arguments: * **File**: A configuration file may be specified via the `init` command line. To specify a file, use the `-backend-config=PATH` option when running `tofu init`. If the file contains secrets it may be kept in a secure data store, such as [Vault](https://www.vaultproject.io/) , in which case it must be downloaded to the local disk before running OpenTofu. * **Command-line key/value pairs**: Key/value pairs can be specified via the `init` command line. Note that many shells retain command-line flags in a history file, so this isn't recommended for secrets. To specify a single key/value pair, use the `-backend-config="KEY=VALUE"` option when running `tofu init`. * **Interactively**: OpenTofu will interactively ask you for the required values, unless interactive input is disabled. OpenTofu will not prompt for optional values. If backend settings are provided in multiple locations, the top-level settings are merged such that any command-line options override the settings in the main configuration and then the command-line options are processed in order, with later options overriding values set by earlier options. The final, merged configuration is stored on disk in the `.terraform` directory, which should be ignored from version control. This means that sensitive information can be omitted from version control, but it will be present in plain text on local disk when running OpenTofu. When using partial configuration, OpenTofu requires at a minimum that an empty backend configuration is specified in one of the root OpenTofu configuration files, to specify the backend type. For example: Code Block terraform { backend "consul" {}} ### File[​](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#file "Direct link to File") A backend configuration file has the contents of the `backend` block as top-level attributes, without the need to wrap it in another `tofu` or `backend` block: Code Block address = "demo.consul.io"path = "example_app/terraform_state"scheme = "https" `*.backendname.tfbackend` (e.g. `config.consul.tfbackend`) is the recommended naming pattern. OpenTofu will not prevent you from using other names but following this convention will help your editor understand the content and likely provide better editing experience as a result. ### Command-line key/value pairs[​](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#command-line-keyvalue-pairs "Direct link to Command-line key/value pairs") The same settings can alternatively be specified on the command line as follows: Code Block $ tofu init \ -backend-config="address=demo.consul.io" \ -backend-config="path=example_app/terraform_state" \ -backend-config="scheme=https" The Consul backend also requires a Consul access token. Per the recommendation above of omitting credentials from the configuration and using other mechanisms, the Consul token would be provided by setting either the `CONSUL_HTTP_TOKEN` or `CONSUL_HTTP_AUTH` environment variables. See the documentation of your chosen backend to learn how to provide credentials to it outside of its main configuration. Variables and Locals[​](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals "Direct link to Variables and Locals") -------------------------------------------------------------------------------------------------------------------------------------------------------------- You may use variables and locals in backend configurations (with restrictions). Backend configuration may not contain any references to data in the state or provider defined functions. All values must be able to be resolved during `tofu init` before the state is available. Warning We recommend against using variables to specify secrets or other sensitive data in your backend configuration. This can leak sensitive credentials if improperly configured. Code Block locals { region = "us-east-1"}terraform { backend "s3" { region = local.region }} Changing Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#changing-configuration "Direct link to Changing Configuration") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can change your backend configuration at any time. You can change both the configuration itself as well as the type of backend (for example from "consul" to "s3"). OpenTofu will automatically detect any changes in your configuration and request a [reinitialization](https://opentofu.org/docs/v1.10/cli/init/) . As part of the reinitialization process, OpenTofu will ask if you'd like to migrate your existing state to the new configuration. This allows you to easily switch from one backend to another. If you're using multiple [workspaces](https://opentofu.org/docs/v1.10/language/state/workspaces/) , OpenTofu can copy all workspaces to the destination. If OpenTofu detects you have multiple workspaces, it will ask if this is what you want to do. If you're just reconfiguring the same backend, OpenTofu will still ask if you want to migrate your state. You can respond "no" in this scenario. Unconfiguring a Backend[​](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#unconfiguring-a-backend "Direct link to Unconfiguring a Backend") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you no longer want to use any backend, you can simply remove the configuration from the file. OpenTofu will detect this like any other change and prompt you to [reinitialize](https://opentofu.org/docs/v1.10/cli/init/) . As part of the reinitialization, OpenTofu will ask if you'd like to migrate your state back down to normal local state. Once this is complete then OpenTofu is back to behaving as it does by default. * [Available Backends](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#available-backends) * [Using a Backend Block](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#using-a-backend-block) * [Credentials and Sensitive Data](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#credentials-and-sensitive-data) * [Backend Types](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#backend-types) * [Default Backend](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#default-backend) * [Initialization](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#initialization) * [Partial Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#partial-configuration) * [File](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#file) * [Command-line key/value pairs](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#command-line-keyvalue-pairs) * [Variables and Locals](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#variables-and-locals) * [Changing Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#changing-configuration) * [Unconfiguring a Backend](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#unconfiguring-a-backend) --- # Style Conventions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/syntax/style/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Style Conventions ================= The OpenTofu parser allows you some flexibility in how you lay out the elements in your configuration files, but the OpenTofu language also has some idiomatic style conventions which we recommend users always follow for consistency between files and modules written by different teams. Automatic source code formatting tools may apply these conventions automatically. Note You can enforce these conventions automatically by running [`tofu fmt`](https://opentofu.org/docs/v1.10/cli/commands/fmt/) . * Indent two spaces for each nesting level. * When multiple arguments with single-line values appear on consecutive lines at the same nesting level, align their equals signs: Code Block ami = "abc123"instance_type = "t2.micro" * When both arguments and blocks appear together inside a block body, place all of the arguments together at the top and then place nested blocks below them. Use one blank line to separate the arguments from the blocks. * Use empty lines to separate logical groups of arguments within a block. * For blocks that contain both arguments and "meta-arguments" (as defined by the OpenTofu language semantics), list meta-arguments first and separate them from other arguments with one blank line. Place meta-argument blocks _last_ and separate them from other blocks with one blank line. Code Block resource "aws_instance" "example" { count = 2 # meta-argument first ami = "abc123" instance_type = "t2.micro" network_interface { # ... } lifecycle { # meta-argument block last create_before_destroy = true }} * Top-level blocks should always be separated from one another by one blank line. Nested blocks should also be separated by blank lines, except when grouping together related blocks of the same type (like multiple `provisioner` blocks in a resource). * Avoid grouping multiple blocks of the same type with other blocks of a different type, unless the block types are defined by semantics to form a family. (For example: `root_block_device`, `ebs_block_device` and `ephemeral_block_device` on `aws_instance` form a family of block types describing AWS block devices, and can therefore be grouped together and mixed.) --- # The for_each Meta-Argument | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page The `for_each` Meta-Argument ============================ By default, a [resource block](https://opentofu.org/docs/v1.10/language/resources/syntax/) configures one real infrastructure object (and similarly, a [module block](https://opentofu.org/docs/v1.10/language/modules/syntax/) includes a child module's contents into the configuration one time). However, sometimes you want to manage several similar objects (like a fixed pool of compute instances) without writing a separate block for each one. OpenTofu has two ways to do this: [`count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) and `for_each`. If a resource or module block includes a `for_each` argument whose value is a map or a set of strings, OpenTofu creates one instance for each member of that map or set. Note A given resource or module block cannot use both `count` and `for_each`. Basic Syntax[​](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#basic-syntax "Direct link to Basic Syntax") ------------------------------------------------------------------------------------------------------------------------------ `for_each` is a meta-argument defined by the OpenTofu language. It can be used with modules and with every resource type. The `for_each` meta-argument accepts a map or a set of strings, and creates an instance for each item in that map or set. Each instance has a distinct infrastructure object associated with it, and each is separately created, updated, or destroyed when the configuration is applied. Map: Code Block resource "azurerm_resource_group" "rg" { for_each = { a_group = "eastus" another_group = "westus2" } name = each.key location = each.value} Set of strings: Code Block resource "aws_iam_user" "the-accounts" { for_each = toset( ["Todd", "James", "Alice", "Dottie"] ) name = each.key} Child module: Code Block # my_buckets.tfmodule "bucket" { for_each = toset(["assets", "media"]) source = "./publish_bucket" name = "${each.key}_bucket"} Code Block # publish_bucket/bucket-and-cloudfront.tfvariable "name" {} # this is the input parameter of the moduleresource "aws_s3_bucket" "example" { # Because var.name includes each.key in the calling # module block, its value will be different for # each instance of this module. bucket = var.name # ...}resource "aws_iam_user" "deploy_user" { # ...} The `each` Object[​](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#the-each-object "Direct link to the-each-object") ----------------------------------------------------------------------------------------------------------------------------------------- In blocks where `for_each` is set, an additional `each` object is available in expressions, so you can modify the configuration of each instance. This object has two attributes: * `each.key` β€”Β The map key (or set member) corresponding to this instance. * `each.value` β€” The map value corresponding to this instance. (If a set was provided, this is the same as `each.key`.) Limitations on values used in `for_each`[​](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#limitations-on-values-used-in-for_each "Direct link to limitations-on-values-used-in-for_each") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The keys of the map (or all the values in the case of a set of strings) must be _known values_, or you will get an error message that `for_each` has dependencies that cannot be determined before apply, and a `-target`/`-exclude` may be needed. `for_each` keys cannot be the result (or rely on the result of) of impure functions, including `uuid`, `bcrypt`, or `timestamp`, as their evaluation is deferred during the main evaluation step. Sensitive values, such as [sensitive input variables](https://opentofu.org/docs/v1.10/language/values/variables/#suppressing-values-in-cli-output) , [sensitive outputs](https://opentofu.org/docs/v1.10/language/values/outputs/#sensitive-suppressing-values-in-cli-output) , or [sensitive resource attributes](https://opentofu.org/docs/v1.10/language/expressions/references/#sensitive-resource-attributes) , cannot be used as arguments to `for_each`. The value used in `for_each` is used to identify the resource instance and will always be disclosed in UI output, which is why sensitive values are not allowed. Attempts to use sensitive values as `for_each` arguments will result in an error. If you transform a value containing sensitive data into an argument to be used in `for_each`, be aware that [most functions in OpenTofu will return a sensitive result if given an argument with any sensitive content](https://opentofu.org/docs/v1.10/language/expressions/function-calls/#using-sensitive-data-as-function-arguments) . In many cases, you can achieve similar results to a function used for this purpose by using a `for` expression. For example, if you would like to call `keys(local.map)`, where `local.map` is an object with sensitive values (but non-sensitive keys), you can create a value to pass to `for_each` with `toset([for k,v in local.map : k])`. Using Expressions in `for_each`[​](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#using-expressions-in-for_each "Direct link to using-expressions-in-for_each") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The `for_each` meta-argument accepts map or set [expressions](https://opentofu.org/docs/v1.10/language/expressions/) . However, unlike most arguments, the `for_each` value must be known _before_ OpenTofu performs any remote resource actions. This means `for_each` can't refer to any resource attributes that aren't known until after a configuration is applied (such as a unique ID generated by the remote API when an object is created). The `for_each` value must be a map or set with one element per desired resource instance. To use a sequence as the `for_each` value, you must use an expression that explicitly returns a set value, like the [toset](https://opentofu.org/docs/v1.10/language/functions/toset/) function. To prevent unwanted surprises during conversion, the `for_each` argument does not implicitly convert lists or tuples to sets. If you need to declare resource instances based on a nested data structure or combinations of elements from multiple data structures you can use OpenTofu expressions and functions to derive a suitable value. For example: * Transform a multi-level nested structure into a flat list by [using nested `for` expressions with the `flatten` function](https://opentofu.org/docs/v1.10/language/functions/flatten/#flattening-nested-structures-for-for_each) . * Produce an exhaustive list of combinations of elements from two or more collections by [using the `setproduct` function inside a `for` expression](https://opentofu.org/docs/v1.10/language/functions/setproduct/#finding-combinations-for-for_each) . ### Chaining `for_each` Between Resources[​](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#chaining-for_each-between-resources "Direct link to chaining-for_each-between-resources") Because a resource using `for_each` appears as a map of objects when used in expressions elsewhere, you can directly use one resource as the `for_each` of another in situations where there is a one-to-one relationship between two sets of objects. For example, in AWS an `aws_vpc` object is commonly associated with a number of other objects that provide additional services to that VPC, such as an "internet gateway". If you are declaring multiple VPC instances using `for_each` then you can chain that `for_each` into another resource to declare an internet gateway for each VPC: Code Block variable "vpcs" { type = map(object({ cidr_block = string }))}resource "aws_vpc" "example" { # One VPC for each element of var.vpcs for_each = var.vpcs # each.value here is a value from var.vpcs cidr_block = each.value.cidr_block}resource "aws_internet_gateway" "example" { # One Internet Gateway per VPC for_each = aws_vpc.example # each.value here is a full aws_vpc object vpc_id = each.value.id}output "vpc_ids" { value = { for k, v in aws_vpc.example : k => v.id } # The VPCs aren't fully functional until their # internet gateways are running. depends_on = [aws_internet_gateway.example]} This chaining pattern explicitly and concisely declares the relationship between the internet gateway instances and the VPC instances, which tells OpenTofu to expect the instance keys for both to always change together, and typically also makes the configuration easier to understand for human maintainers. Referring to Instances[​](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#referring-to-instances "Direct link to Referring to Instances") ------------------------------------------------------------------------------------------------------------------------------------------------------------ When `for_each` is set, OpenTofu distinguishes between the block itself and the multiple _resource or module instances_ associated with it. Instances are identified by a map key (or set member) from the value provided to `for_each`. * `.` or `module.` (for example, `azurerm_resource_group.rg`) refers to the block. * `.[]` or `module.[]` (for example, `azurerm_resource_group.rg["a_group"]`, `azurerm_resource_group.rg["another_group"]`, etc.) refers to individual instances. This is different from resources and modules without `count` or `for_each`, which can be referenced without an index or key. Similarly, resources from child modules with multiple instances are prefixed with `module.[]` when displayed in plan output and elsewhere in the UI. For a module without `count` or `for_each`, the address will not contain the module index as the module's name suffices to reference the module. Note Within nested `provisioner` or `connection` blocks, the special `self` object refers to the current _resource instance,_ not the resource block as a whole. Using Sets[​](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#using-sets "Direct link to Using Sets") ------------------------------------------------------------------------------------------------------------------------ The OpenTofu language doesn't have a literal syntax for [set values](https://opentofu.org/docs/v1.10/language/expressions/type-constraints/#collection-types) , but you can use the `toset` function to explicitly convert a list of strings to a set: Code Block locals { subnet_ids = toset([ "subnet-abcdef", "subnet-012345", ])}resource "aws_instance" "server" { for_each = local.subnet_ids ami = "ami-a1b2c3d4" instance_type = "t2.micro" subnet_id = each.key # note: each.key and each.value are the same for a set tags = { Name = "Server ${each.key}" }} Conversion from list to set discards the ordering of the items in the list and removes any duplicate elements. `toset(["b", "a", "b"])` will produce a set containing only `"a"` and `"b"` in no particular order; the second `"b"` is discarded. If you are writing a module with an [input variable](https://opentofu.org/docs/v1.10/language/values/variables/) that will be used as a set of strings for `for_each`, you can set its type to `set(string)` to avoid the need for an explicit type conversion: Code Block variable "subnet_ids" { type = set(string)}resource "aws_instance" "server" { for_each = var.subnet_ids # (and the other arguments as above)} * [Basic Syntax](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#basic-syntax) * [The `each` Object](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#the-each-object) * [Limitations on values used in `for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#limitations-on-values-used-in-for_each) * [Using Expressions in `for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#using-expressions-in-for_each) * [Chaining `for_each` Between Resources](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#chaining-for_each-between-resources) * [Referring to Instances](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#referring-to-instances) * [Using Sets](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/#using-sets) --- # Import Existing Resources | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/state/import/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Import Existing Resources ========================= OpenTofu is able to import existing infrastructure. This allows you to take resources you have created by some other means and bring them under OpenTofu management. To learn more, see [Import](https://opentofu.org/docs/v1.10/language/import/) . --- # Provider Configuration | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/providers/configuration/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provider Configuration ====================== Providers allow OpenTofu to interact with cloud providers, SaaS providers, and other APIs. Some providers require you to configure them with endpoint URLs, cloud regions, or other settings before OpenTofu can use them. This page documents how to configure settings for providers. Additionally, all OpenTofu configurations must declare which providers they require so that OpenTofu can install and use them. The [Provider Requirements](https://opentofu.org/docs/v1.10/language/providers/requirements/) page documents how to declare providers so OpenTofu can install them. Provider Configuration[​](https://opentofu.org/docs/v1.10/language/providers/configuration/#provider-configuration-1 "Direct link to Provider Configuration") -------------------------------------------------------------------------------------------------------------------------------------------------------------- Provider configurations belong in the root module of an OpenTofu configuration. (Child modules receive their provider configurations from the root module; for more information, see [The Module `providers` Meta-Argument](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/) and [Module Development: Providers Within Modules](https://opentofu.org/docs/v1.10/language/modules/develop/providers/) .) A provider configuration is defined using a `provider` block: Code Block provider "google" { project = "acme-app" region = "us-central1"} The name given in the block header (`"google"` in this example) is the [local name](https://opentofu.org/docs/v1.10/language/providers/requirements/#local-names) of the provider to configure. Each module has its own namespace of provider local names, defined in its `required_providers` block. The body of the block (between `{` and `}`) contains configuration arguments for the provider. Most arguments in this section are defined by the provider itself; in this example both `project` and `region` are specific to the `google` provider. You can use [expressions](https://opentofu.org/docs/v1.10/language/expressions/) in the values of these configuration arguments, but can only refer to values that are known before the configuration is applied. This means you can safely reference input variables, but not attributes exported by resources unless they are defined directly in the configuration or documented as being available during the planning phase. A provider's documentation should list which configuration arguments it expects. For providers distributed on the [Public OpenTofu Registry](https://registry.opentofu.org/) , versioned documentation is available on each provider's page, via the "Documentation" link in the provider's header. Some providers can use shell environment variables (or other alternate sources, like VM instance profiles) as values for some of their arguments; when available, we recommend using this as a way to keep credentials out of your version-controlled OpenTofu code. There are also two "meta-arguments" that are defined by OpenTofu itself and available for all `provider` blocks: * [`alias`, for defining additional configurations for the same provider](https://opentofu.org/docs/v1.10/language/providers/configuration/#alias-multiple-provider-configurations) * [`for_each`, for defining multiple dynamic instances of a provider configuration](https://opentofu.org/docs/v1.10/language/providers/configuration/#for_each-multiple-instances-of-a-provider-configuration) * [`version`, which we no longer recommend](https://opentofu.org/docs/v1.10/language/providers/configuration/#provider-versions) (use [provider requirements](https://opentofu.org/docs/v1.10/language/providers/requirements/) instead) Unlike many other objects in the OpenTofu language, a `provider` block may be omitted if its contents would otherwise be empty. OpenTofu assumes an empty default configuration for any provider that is not explicitly configured. `alias`: Multiple Provider Configurations[​](https://opentofu.org/docs/v1.10/language/providers/configuration/#alias-multiple-provider-configurations "Direct link to alias-multiple-provider-configurations") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can optionally define multiple configurations for the same provider, and select which one to use on a per-resource or per-module basis. The primary reason for this is to support multiple regions for a cloud platform; other examples include targeting multiple Docker hosts, multiple Consul hosts, etc. To create multiple configurations for a given provider, include multiple `provider` blocks with the same provider name. For each additional non-default configuration, use the `alias` meta-argument to provide an extra name segment. A provider configuration with an alias is called an _alternate provider configuration_. For example: Code Block # The default provider configuration; resources that begin with `aws_` will use# it as the default, and it can be referenced as `aws`.provider "aws" { region = "us-east-1"}# Alternate provider configuration for west coast region; resources can# reference this as `aws.west`.provider "aws" { alias = "west" region = "us-west-2"} To declare a configuration alias within a module in order to receive an alternate provider configuration from the parent module, add the `configuration_aliases` argument to that provider's `required_providers` entry. The following example declares both the `mycloud` and `mycloud.alternate` provider configuration names within the containing module: Code Block terraform { required_providers { mycloud = { source = "mycorp/mycloud" version = "~> 1.0" configuration_aliases = [ mycloud.alternate ] } }} Default Provider Configurations[​](https://opentofu.org/docs/v1.10/language/providers/configuration/#default-provider-configurations "Direct link to Default Provider Configurations") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A `provider` block without an `alias` argument is the _default_ configuration for that provider. Resources that don't set the `provider` meta-argument will use the default provider configuration that matches the first word of the resource type name. (For example, an `aws_instance` resource uses the default `aws` provider configuration unless otherwise stated.) If there is no `provider` block defining the default configuration for a provider, OpenTofu automatically infers an empty default provider configuration for that provider. If the provider's configuration schema includes any required arguments then the empty configuration would be invalid, and so an explicit `provider` block is required. A default provider configuration is not required nor inferred if all resources in a module explicitly select a different provider configuration using the `provider` meta-argument in their `resource` or `data` blocks. `for_each`: Multiple instances of a provider configuration[​](https://opentofu.org/docs/v1.10/language/providers/configuration/#for_each-multiple-instances-of-a-provider-configuration "Direct link to for_each-multiple-instances-of-a-provider-configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Sometimes it's necessary to declare multiple instances of a provider dynamically based on some other data available in your configuration, such as an input variable. For example, a configuration that declares a foundational set of infrastructure for each AWS region that an organization is using might offer an input variable for specifying those regions, but the `hashicorp/aws` provider supports only one region per instance of the provider and so it would not be possible to declare infrastructure across a dynamic set of regions using only static provider configurations. Any alternate provider configuration (declared using the `alias` argument) can optionally also include the `for_each` argument to declare that the configuration should be instantiated multiple times based on a collection value: Code Block variable "aws_regions" { type = map(object({ vpc_cidr_block = string }))}provider "aws" { alias = "by_region" for_each = var.aws_regions region = each.key} Without the `for_each` argument, a `provider` block always declares only a single instance of the corresponding provider. A provider configuration which includes the `for_each` argument instead declares _zero or more_ provider instances where each corresponds to one element from the `for_each` collection, each configured systematically based on the same configuration block. Each instance has an _instance key_ which uniquely identifies the instance among all instances belonging to the same provider configuration. The value assigned to `for_each` must be of either a map type, an object type, or be a set of strings. For a map or object type, the element key or attribute name becomes the instance key. For a set of strings, the element value itself becomes the instance key. An operator of this configuration must provide a map value for the `aws_regions` input variable, where each element's key is a valid AWS region name and its value is an object describing the unique settings for that region. For example, in a `terraform.tfvars` file: Code Block aws_regions = { eu-central-2 = { vpc_cidr_block = "10.1.0.0/16" } ap-northeast-1 = { vpc_cidr_block = "10.2.0.0/16" }} The `for_each` argument can only be used in combination with `alias`, because the default configuration for each provider must always have exactly one instance so that OpenTofu can select it automatically when appropriate. Selecting Alternate Provider Configurations[​](https://opentofu.org/docs/v1.10/language/providers/configuration/#selecting-alternate-provider-configurations "Direct link to Selecting Alternate Provider Configurations") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Each resource in your OpenTofu configuration must be bound to one provider configuration. By default, each resource is bound to a [default provider configuration](https://opentofu.org/docs/v1.10/language/providers/configuration/#default-provider-configurations) chosen automatically based on the first segment of the resource type name. For example, a `resource "azurerm_subnet" "example"` block would be bound to the default configuration for whichever provider has the local name "azurerm" in the module where the resource is declared. To use an alternate provider configuration, a `resource` or `data` block must include [the `provider` Meta-Argument](https://opentofu.org/docs/v1.10/language/meta-arguments/resource-provider/) , with a [provider instance reference](https://opentofu.org/docs/v1.10/language/providers/configuration/#referring-to-provider-instances) that includes the selected configuration's alias: Code Block resource "aws_instance" "foo" { provider = aws.west # ...} If the selected configuration uses the `for_each` argument to declare multiple instances then the `provider` argument must also include an instance key expression to select one instance of the provider configuration per resource instance as described in the next section. Omitting the `provider` argument is equivalent to setting it to choose the default configuration for the provider whose local name matches the resource type name's prefix: Code Block resource "aws_instance" "foo" { provider = aws # ...} Referring to Provider Instances[​](https://opentofu.org/docs/v1.10/language/providers/configuration/#referring-to-provider-instances "Direct link to Referring to Provider Instances") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To explicitly refer to provider configurations, OpenTofu uses a provider-configuration-specific reference syntax of the form `.`. For example, `aws.west` refers to the `provider "aws"` block with `alias = "west"`. This syntax uses similar symbols to a normal [expression reference](https://opentofu.org/docs/v1.10/language/expressions/references/) , but provider references are not normal expressions and can only be used in some special locations: * [The `provider` meta-argument of a `resource` or `data` block](https://opentofu.org/docs/v1.10/language/meta-arguments/resource-provider/) * [The `providers` meta-argument of a `module` block](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/) For a provider configuration that does not include `for_each`, the same syntax used to refer to the configuration is also a reference to its single provider instance, so in most cases you can think of a provider configuration reference and a provider instance reference as equivalent. However, when a provider configuration declares zero or more dynamic instances using `for_each` the reference syntax grows to include an additional component which specifies which instance to select using the configuration's instance keys. For example, `aws.by_region["eu-west-1"]` refers to whichever instance of `aws.by_region` has the instance key `"eu-west-1"`. The expression in square brackets uses [normal expression syntax](https://opentofu.org/docs/v1.10/language/expressions/) , and typically the instance key would be selected dynamically for each instance of a resource rather than hard-coded. For example: Code Block variable "aws_regions" { type = map(object({ vpc_cidr_block = string }))}provider "aws" { alias = "by_region" for_each = var.aws_regions region = each.key}resource "aws_vpc" "private" { # This expression filters var.aws_regions to include only # the elements whose value is not null. Refer to the # warning in the text below for more information. for_each = { for region, config in var.aws_regions : region => config if config != null } provider = aws.by_region[each.key] cidr_block = each.value.vpc_cidr_block} The `resource "aws_vpc" "private"` block uses `for_each` to declare one instance of the resource for each non-null element of `var.aws_regions`. The `provider` argument then uses `each.key` to select a different instance of `aws.by_region` for each instance of the resource, so that each would be declared in a different region. You can also choose a dynamic instance from a provider configuration for all resources in a child module as part of a `module` block. Refer to [Module instances with differing provider instances](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/#module-instances-with-differing-provider-instances) for more information. Although the instance key expression in square brackets is dynamic, the provider configuration reference is static so that OpenTofu can infer the dependencies between `resource` blocks and `provider` blocks before evaluating any expressions. The dependencies then ensure that OpenTofu can resolve dynamic expressions in the correct order. This means that all instances of a particular resource must be bound to instances of the same provider configuration block, but can they each be bound to a different instance. Warning **The `for_each` expression for a resource must not exactly match the `for_each` expression for its associated provider configuration.** OpenTofu uses a provider instance to plan and apply _all_ actions related to a resource instance, including destroying a resource instance that has been removed from the configuration. Therefore the provider instance associated with any resource instance must always remain in the configuration for at least one more plan/apply round after the resource instance has been removed, or OpenTofu will fail to plan to destroy the resource instance. The above example uses a null element in `var.aws_regions` to represent that a provider instance is needed but no resource instances should be associated with it. Setting a particular region's element to `null` would therefore cause OpenTofu to propose to destroy the `aws_vpc.private` instance for that region while retaining the provider instance needed to plan and apply that action. You can then remove the element altogether on the next round, once all of the associated resource instances have been destroyed. ### Passing provider configurations between modules[​](https://opentofu.org/docs/v1.10/language/providers/configuration/#passing-provider-configurations-between-modules "Direct link to Passing provider configurations between modules") Each module has its own separate namespace of provider configurations, but it's possible for a parent module to pass some or all of its provider configurations into provider configuration addresses declared in a child module. For more information, refer to [The `providers` Meta-Argument in `module` blocks](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/) . `version` (Deprecated)[​](https://opentofu.org/docs/v1.10/language/providers/configuration/#version-deprecated "Direct link to version-deprecated") ---------------------------------------------------------------------------------------------------------------------------------------------------- The `version` meta-argument specifies a version constraint for a provider, and works the same way as the `version` argument in a [`required_providers` block](https://opentofu.org/docs/v1.10/language/providers/requirements/) . The version constraint in a provider configuration is only used if `required_providers` does not include one for that provider. Always declare provider version constraints in [the `required_providers` block](https://opentofu.org/docs/v1.10/language/providers/requirements/) . * [Provider Configuration](https://opentofu.org/docs/v1.10/language/providers/configuration/#provider-configuration-1) * [`alias`: Multiple Provider Configurations](https://opentofu.org/docs/v1.10/language/providers/configuration/#alias-multiple-provider-configurations) * [Default Provider Configurations](https://opentofu.org/docs/v1.10/language/providers/configuration/#default-provider-configurations) * [`for_each`: Multiple instances of a provider configuration](https://opentofu.org/docs/v1.10/language/providers/configuration/#for_each-multiple-instances-of-a-provider-configuration) * [Selecting Alternate Provider Configurations](https://opentofu.org/docs/v1.10/language/providers/configuration/#selecting-alternate-provider-configurations) * [Referring to Provider Instances](https://opentofu.org/docs/v1.10/language/providers/configuration/#referring-to-provider-instances) * [Passing provider configurations between modules](https://opentofu.org/docs/v1.10/language/providers/configuration/#passing-provider-configurations-between-modules) * [`version` (Deprecated)](https://opentofu.org/docs/v1.10/language/providers/configuration/#version-deprecated) --- # Configuration Syntax | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/syntax/configuration/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Configuration Syntax ==================== Other pages in this section have described various configuration constructs that can appear in the OpenTofu language. This page describes the lower-level syntax of the language in more detail, revealing the building blocks that those constructs are built from. This page describes the _native syntax_ of the OpenTofu language, which is a rich language designed to be relatively easy for humans to read and write. The constructs in the OpenTofu language can also be expressed in [JSON syntax](https://opentofu.org/docs/v1.10/language/syntax/json/) , which is harder for humans to read and edit but easier to generate and parse programmatically. This low-level syntax of the OpenTofu language is defined in terms of a syntax called _HCL_, which is also used by configuration languages in other applications, and in particular other HashiCorp products. It is not necessary to know all of the details of HCL syntax in order to use OpenTofu, and so this page summarizes the most important details. If you are interested, you can find a full definition of HCL syntax in [the HCL native syntax specification](https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md) . Arguments and Blocks[​](https://opentofu.org/docs/v1.10/language/syntax/configuration/#arguments-and-blocks "Direct link to Arguments and Blocks") --------------------------------------------------------------------------------------------------------------------------------------------------- The OpenTofu language syntax is built around two key syntax constructs: arguments and blocks. ### Arguments[​](https://opentofu.org/docs/v1.10/language/syntax/configuration/#arguments "Direct link to Arguments") An _argument_ assigns a value to a particular name: Code Block image_id = "abc123" The identifier before the equals sign is the _argument name_, and the expression after the equals sign is the argument's value. The context where the argument appears determines what value types are valid (for example, each resource type has a schema that defines the types of its arguments), but many arguments accept arbitrary [expressions](https://opentofu.org/docs/v1.10/language/expressions/) , which allow the value to either be specified literally or generated from other values programmatically. Note OpenTofu's configuration language is based on a more general language called HCL, and HCL's documentation usually uses the word "attribute" instead of "argument." These words are similar enough to be interchangeable in this context, and experienced OpenTofu users might use either term in casual conversation. But because OpenTofu also interacts with several _other_ things called "attributes" (in particular, OpenTofu resources have attributes like `id` that can be referenced from expressions but can't be assigned values in configuration), we've chosen to use "argument" in the OpenTofu documentation when referring to this syntax construct. ### Blocks[​](https://opentofu.org/docs/v1.10/language/syntax/configuration/#blocks "Direct link to Blocks") A _block_ is a container for other content: Code Block resource "aws_instance" "example" { ami = "abc123" network_interface { # ... }} A block has a _type_ (`resource` in this example). Each block type defines how many _labels_ must follow the type keyword. The `resource` block type expects two labels, which are `aws_instance` and `example` in the example above. A particular block type may have any number of required labels, or it may require none as with the nested `network_interface` block type. After the block type keyword and any labels, the block _body_ is delimited by the `{` and `}` characters. Within the block body, further arguments and blocks may be nested, creating a hierarchy of blocks and their associated arguments. The OpenTofu language uses a limited number of _top-level block types,_ which are blocks that can appear outside of any other block in a configuration file. Most of OpenTofu's features (including resources, input variables, output values, data sources, etc.) are implemented as top-level blocks. Identifiers[​](https://opentofu.org/docs/v1.10/language/syntax/configuration/#identifiers "Direct link to Identifiers") ------------------------------------------------------------------------------------------------------------------------ Argument names, block type names, and the names of most OpenTofu-specific constructs like resources, input variables, etc. are all _identifiers_. Identifiers can contain letters, digits, underscores (`_`), and hyphens (`-`). The first character of an identifier must not be a digit, to avoid ambiguity with literal numbers. For complete identifier rules, OpenTofu implements [the Unicode identifier syntax](http://unicode.org/reports/tr31/) , extended to include the ASCII hyphen character `-`. Comments[​](https://opentofu.org/docs/v1.10/language/syntax/configuration/#comments "Direct link to Comments") --------------------------------------------------------------------------------------------------------------- The OpenTofu language supports three different syntaxes for comments: * `#` begins a single-line comment, ending at the end of the line. * `//` also begins a single-line comment, as an alternative to `#`. * `/*` and `*/` are start and end delimiters for a comment that might span over multiple lines. The `#` single-line comment style is the default comment style and should be used in most cases. Automatic configuration formatting tools may automatically transform `//` comments into `#` comments, since the double-slash style is not idiomatic. Character Encoding and Line Endings[​](https://opentofu.org/docs/v1.10/language/syntax/configuration/#character-encoding-and-line-endings "Direct link to Character Encoding and Line Endings") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ OpenTofu configuration files must always be UTF-8 encoded. While the delimiters of the language are all ASCII characters, OpenTofu accepts non-ASCII characters in identifiers, comments, and string values. OpenTofu accepts configuration files with either Unix-style line endings (LF only) or Windows-style line endings (CR then LF), but the idiomatic style is to use the Unix convention, and so automatic configuration formatting tools may automatically transform CRLF endings to LF. * [Arguments and Blocks](https://opentofu.org/docs/v1.10/language/syntax/configuration/#arguments-and-blocks) * [Arguments](https://opentofu.org/docs/v1.10/language/syntax/configuration/#arguments) * [Blocks](https://opentofu.org/docs/v1.10/language/syntax/configuration/#blocks) * [Identifiers](https://opentofu.org/docs/v1.10/language/syntax/configuration/#identifiers) * [Comments](https://opentofu.org/docs/v1.10/language/syntax/configuration/#comments) * [Character Encoding and Line Endings](https://opentofu.org/docs/v1.10/language/syntax/configuration/#character-encoding-and-line-endings) --- # Local Values | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/values/locals/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Local Values ============ A local value assigns a name to an [expression](https://opentofu.org/docs/v1.10/language/expressions/) , so you can use the name multiple times within a module instead of repeating the expression. If you're familiar with traditional programming languages, it can be useful to compare modules to function definitions: * [Input variables](https://opentofu.org/docs/v1.10/language/values/variables/) are like function arguments. * [Output values](https://opentofu.org/docs/v1.10/language/values/outputs/) are like function return values. * Local values are like a function's temporary local variables. Note For brevity, local values are often referred to as just "locals" when the meaning is clear from context. Declaring a Local Value[​](https://opentofu.org/docs/v1.10/language/values/locals/#declaring-a-local-value "Direct link to Declaring a Local Value") ----------------------------------------------------------------------------------------------------------------------------------------------------- A set of related local values can be declared together in a single `locals` block: Code Block locals { service_name = "forum" owner = "Community Team"} The expressions in local values are not limited to literal constants; they can also reference other values in the module in order to transform or combine them, including variables, resource attributes, or other local values: Code Block locals { # Ids for multiple sets of EC2 instances, merged together instance_ids = concat(aws_instance.blue.*.id, aws_instance.green.*.id)}locals { # Common tags to be assigned to all resources common_tags = { Service = local.service_name Owner = local.owner }} Using Local Values[​](https://opentofu.org/docs/v1.10/language/values/locals/#using-local-values "Direct link to Using Local Values") -------------------------------------------------------------------------------------------------------------------------------------- Once a local value is declared, you can reference it in [expressions](https://opentofu.org/docs/v1.10/language/expressions/) as `local.`. Note Local values are _created_ by a `locals` block (plural), but you _reference_ them as attributes on an object named `local` (singular). Make sure to leave off the "s" when referencing a local value! Code Block resource "aws_instance" "example" { # ... tags = local.common_tags} A local value can only be accessed in expressions within the module where it was declared. When To Use Local Values[​](https://opentofu.org/docs/v1.10/language/values/locals/#when-to-use-local-values "Direct link to When To Use Local Values") -------------------------------------------------------------------------------------------------------------------------------------------------------- Local values can be helpful to avoid repeating the same values or expressions multiple times in a configuration, but if overused they can also make a configuration hard to read by future maintainers by hiding the actual values used. Use local values only in moderation, in situations where a single value or result is used in many places _and_ that value is likely to be changed in future. The ability to easily change the value in a central place is the key advantage of local values. * [Declaring a Local Value](https://opentofu.org/docs/v1.10/language/values/locals/#declaring-a-local-value) * [Using Local Values](https://opentofu.org/docs/v1.10/language/values/locals/#using-local-values) * [When To Use Local Values](https://opentofu.org/docs/v1.10/language/values/locals/#when-to-use-local-values) --- # Cloud Backend Settings | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/cloud/settings/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Cloud Backend Settings ====================== OpenTofu CLI can integrate with a cloud backend, acting as a client for it. You must configure the following settings to use the cloud backend for a particular working directory: * Provide credentials to access the cloud backend, preferably by using the [`tofu login`](https://opentofu.org/docs/v1.11/cli/commands/login/) command. * Add a `cloud` block to the directory's OpenTofu configuration, to specify which organization and workspace(s) to use. * Optionally, use a `.terraformignore` file to specify files that shouldn't be uploaded with the OpenTofu configuration when running plans and applies. After adding or changing a `cloud` block, you must run `tofu init`. The `cloud` Block[​](https://opentofu.org/docs/v1.11/cli/cloud/settings/#the-cloud-block "Direct link to the-cloud-block") --------------------------------------------------------------------------------------------------------------------------- The `cloud` block is a nested block within the top-level `terraform` settings block. It specifies which cloud backend workspaces to use for the current working directory. Code Block terraform { cloud { organization = "my-org" hostname = "app.example.org" workspaces { project = "networking-development" tags = ["networking", "source:cli"] } }} The `cloud` block also has some special restrictions: * A configuration can only provide one `cloud` block. * A `cloud` block cannot be used with [state backends](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/) . A configuration can use one or the other, but not both. * A `cloud` block cannot refer to named values (like input variables, locals, or data source attributes). The `cloud` block only affects OpenTofu CLI's behavior. When the cloud backend uses a configuration that contains a cloud block - for example, when a workspace is configured to use a VCS provider directly - it ignores the block and behaves according to its own workspace settings. ### Arguments[​](https://opentofu.org/docs/v1.11/cli/cloud/settings/#arguments "Direct link to Arguments") The `cloud` block supports the following configuration arguments: * `hostname` - (Required) The hostname of the cloud backend. * `organization` - (Required) The name of the organization containing the workspace(s) the current configuration should use. * `workspaces` - (Required) A nested block that specifies which remote cloud backend workspaces to use for the current configuration. The `workspaces` block must contain **exactly one** of the following arguments, each denoting a strategy for how workspaces should be mapped: * `tags` - (Optional) A set of cloud backend workspace tags. You will be able to use this working directory with any workspaces that have all of the specified tags, and can use [the `tofu workspace` commands](https://opentofu.org/docs/v1.11/cli/workspaces/) to switch between them or create new workspaces. New workspaces will automatically have the specified tags. This option conflicts with `name`. * `name` - (Optional) The name of a single cloud backend workspace. You will only be able to use the workspace specified in the configuration with this working directory, and cannot manage workspaces from the CLI (e.g. `tofu workspace select` or `tofu workspace new`). This option conflicts with `tags`. * `project` - (Optional) The name of a cloud backend project. Workspaces that need created will will be created within this project. `tofu workspace list` will be filtered by workspaces in the supplied project. * `token` - (Optional) The token used to authenticate with the cloud backend. We recommend omitting the token from the configuration, and instead using [`tofu login`](https://opentofu.org/docs/v1.11/cli/commands/login/) or manually configuring `credentials` in the [CLI config file](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials) . ### Environment Variables[​](https://opentofu.org/docs/v1.11/cli/cloud/settings/#environment-variables "Direct link to Environment Variables") You can use environment variables to configure one or more `cloud` block attributes. This is helpful when you want to configure OpenTofu as part of a Continuous Integration (CI) pipeline. OpenTofu only reads these variables if the corresponding attribute is omitted from your configuration file. If you choose to configure the `cloud` block entirely through environment variables, you must still add an empty `cloud` block in your configuration file. Warning Remote execution with non-interactive workflows requires auto-approved deployments. Minimize risk of unpredictable infrastructure changes and configuration drift by making sure that no one can change your infrastructure outside of your automated build pipeline. Use the following environment variables to configure the `cloud` block: * `TF_CLOUD_ORGANIZATION` - The name of the organization. OpenTofu reads this variable when `organization` omitted from the `cloud` block. If both are specified, the configuration takes precedence. * `TF_CLOUD_HOSTNAME` - The hostname of the cloud backend. OpenTofu reads this when `hostname` is omitted from the `cloud` block. If both are specified, the configuration takes precedence. * `TF_CLOUD_PROJECT` - The name of a cloud backend project. OpenTofu reads this when `workspaces.project` is omitted from the `cloud` block. If both are specified, the cloud block configuration takes precedence. * `TF_WORKSPACE` - The name of a single cloud backend workspace. OpenTofu reads this when `workspaces` is omitted from the `cloud` block. The cloud backend will not create a new workspace from this variable; the workspace must exist in the specified organization. You can set `TF_WORKSPACE` if the `cloud` block uses tags. However, the selected `TF_WORKSPACE` must have a set of tags that match the tags in the `cloud` block. This variable also selects the workspace in your local environment. Refer to [TF\_WORKSPACE](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_workspace) for details. Excluding Files from Upload with .terraformignore[​](https://opentofu.org/docs/v1.11/cli/cloud/settings/#excluding-files-from-upload-with-terraformignore "Direct link to Excluding Files from Upload with .terraformignore") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ When executing a remote `plan` or `apply` in a CLI-driven run, a copy of your configuration directory is uploaded to the cloud backend. You can define paths to exclude from upload by adding a `.terraformignore` file at the root of your configuration directory. If this file is not present, the upload will exclude the following by default: * `.git/` directories * `.terraform/` directories (exclusive of `.terraform/modules`) The rules in `.terraformignore` file resemble the rules allowed in a [.gitignore file](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#_ignoring) : * Comments (starting with `#`) or blank lines are ignored. * End a pattern with a forward slash `/` to specify a directory. * Negate a pattern by starting it with an exclamation point `!`. Note Unlike `.gitignore`, only the `.terraformignore` at the root of the configuration directory is considered. * [The `cloud` Block](https://opentofu.org/docs/v1.11/cli/cloud/settings/#the-cloud-block) * [Arguments](https://opentofu.org/docs/v1.11/cli/cloud/settings/#arguments) * [Environment Variables](https://opentofu.org/docs/v1.11/cli/cloud/settings/#environment-variables) * [Excluding Files from Upload with .terraformignore](https://opentofu.org/docs/v1.11/cli/cloud/settings/#excluding-files-from-upload-with-terraformignore) --- # OpenTofu Internals | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/internals/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu Internals ================== This section covers the internals of OpenTofu and explains how plans are generated, the lifecycle of a provider, etc. The goal of this section is to remove any notion of "magic" from OpenTofu. We want you to be able to trust and understand what OpenTofu is doing to function. Note Knowledge of OpenTofu internals is not required to use OpenTofu. If you aren't interested in the internals of OpenTofu, you may safely skip this section. --- # Backend Type: pg | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/backends/pg/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Backend Type: pg ================ Stores the state in a [Postgres database](https://www.postgresql.org/) version 10 or newer. This backend supports [state locking](https://opentofu.org/docs/v1.10/language/state/locking/) . Warning OpenTofu 1.10 changed how workspace creation locking works. It is unsafe to use `pg` backend with multiple OpenTofu versions (under 1.10) in parallel if those are sharing the same underlying database. Example Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/pg/#example-configuration "Direct link to Example Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------ Code Block terraform { backend "pg" { conn_str = "postgres://user:[emailΒ protected]/tofu_backend" }} Before initializing the backend with `tofu init`, the database must already exist: Code Block createdb tofu_backend This `createdb` command is found in [Postgres client applications](https://www.postgresql.org/docs/10/reference-client.html) which are installed along with the database server. ### Using environment variables[​](https://opentofu.org/docs/v1.10/language/settings/backends/pg/#using-environment-variables "Direct link to Using environment variables") We recommend using environment variables to configure the `pg` backend in order not to have sensitive credentials written to disk and committed to source control. The `pg` backend supports the standard [`libpq` environment variables](https://www.postgresql.org/docs/current/libpq-envars.html) . The backend can be configured either by giving the whole configuration as an environment variable: Code Block terraform { backend "pg" {}} Code Block $ export PG_CONN_STR=postgres://user:[emailΒ protected]/tofu_backend$ tofu init or just the sensitive parameters: Code Block terraform { backend "pg" { conn_str = "postgres://db.example.com/tofu_backend" }} Code Block $ export PGUSER=user$ read -s PGPASSWORD$ export PGPASSWORD$ tofu init Data Source Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/pg/#data-source-configuration "Direct link to Data Source Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ To make use of the pg remote state in another configuration, use the [`terraform_remote_state` data source](https://opentofu.org/docs/v1.10/language/state/remote-state-data/) . Code Block data "terraform_remote_state" "network" { backend = "pg" config = { conn_str = "postgres://localhost/tofu_backend" }} Configuration Variables[​](https://opentofu.org/docs/v1.10/language/settings/backends/pg/#configuration-variables "Direct link to Configuration Variables") ------------------------------------------------------------------------------------------------------------------------------------------------------------ Warning We recommend using environment variables to supply credentials and other sensitive data. If you use `-backend-config` or hardcode these values directly in your configuration, OpenTofu will include these values in both the `.terraform` subdirectory and in plan files. Refer to [Credentials and Sensitive Data](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#credentials-and-sensitive-data) for details. The following configuration options or environment variables are supported: * `conn_str` - Postgres connection string; a `postgres://` URL. The `PG_CONN_STR` and [standard `libpq`](https://www.postgresql.org/docs/current/libpq-envars.html) environment variables can also be used to indicate how to connect to the PostgreSQL database. * `schema_name` - Name of the automatically-managed Postgres schema, default to `terraform_remote_state`. Can also be set using the `PG_SCHEMA_NAME` environment variable. * `skip_schema_creation` - If set to `true`, the Postgres schema must already exist. Can also be set using the `PG_SKIP_SCHEMA_CREATION` environment variable. OpenTofu won't try to create the schema, this is useful when it has already been created by a database administrator. * `table_name` - Name of the automatically-managed Postgres table, default to `states`. Can also be set using the `PG_TABLE_NAME` environment variable. * `skip_table_creation` - If set to `true`, the Postgres table must already exist. Can also be set using the `PG_SKIP_TABLE_CREATION` environment variable. OpenTofu won't try to create the table, this is useful when it has already been created by a database administrator. * `index_name` - Name of the automatically-managed Postgres index, default to `states_by_name`. Can also be set using the `PG_INDEX_NAME` environment variable. * `skip_index_creation` - If set to `true`, the Postgres index must already exist. Can also be set using the `PG_SKIP_INDEX_CREATION` environment variable. OpenTofu won't try to create the index, this is useful when it has already been created by a database administrator. Please, keep in mind, that if `table_name` or `schema_name` is changed, you would need to manually migrate the existing state data. Technical Design[​](https://opentofu.org/docs/v1.10/language/settings/backends/pg/#technical-design "Direct link to Technical Design") --------------------------------------------------------------------------------------------------------------------------------------- This backend creates a table with a name defined by `table_name` in the automatically-managed Postgres schema configured by the `schema_name` variable. The table is keyed by the [workspace](https://opentofu.org/docs/v1.10/language/state/workspaces/) name. If workspaces are not in use, the name `default` is used. Locking is supported using [Postgres advisory locks](https://www.postgresql.org/docs/9.5/explicit-locking.html#ADVISORY-LOCKS) . [`force-unlock`](https://opentofu.org/docs/v1.10/cli/commands/force-unlock/) is not supported, because these database-native locks will automatically unlock when the session is aborted or the connection fails. To see outstanding locks in a Postgres server, use the [`pg_locks` system view](https://www.postgresql.org/docs/9.5/view-pg-locks.html) . Advisory locks are used for multiple scenarios: state updates and state creation. When the state is updated, advisory lock is acquired with state ID. Otherwise, on state (and workspace) creation, it is acquired with the hash of schema name. This way, multiple backend configurations doesn't affect each other, when the database is shared. The table used for state contains: * a serial integer `id`, used as the key for advisory locks * the workspace `name` key as _text_ with a unique index * the OpenTofu state `data` as _text_ * [Example Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/pg/#example-configuration) * [Using environment variables](https://opentofu.org/docs/v1.10/language/settings/backends/pg/#using-environment-variables) * [Data Source Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/pg/#data-source-configuration) * [Configuration Variables](https://opentofu.org/docs/v1.10/language/settings/backends/pg/#configuration-variables) * [Technical Design](https://opentofu.org/docs/v1.10/language/settings/backends/pg/#technical-design) --- # Module Blocks | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/modules/syntax/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Module Blocks ============= A _module_ is a container for multiple resources that are used together. Every OpenTofu configuration has at least one module, known as its _root module_, which consists of the resources defined in the `.tf` and `.tofu` files in the main working directory. A module can call other modules, which lets you include the child module's resources into the configuration in a concise way. Modules can also be called multiple times, either within the same configuration or in separate configurations, allowing resource configurations to be packaged and re-used. This page describes how to call one module from another. For more information about creating re-usable child modules, see [Module Development](https://opentofu.org/docs/v1.10/language/modules/develop/) . Calling a Child Module[​](https://opentofu.org/docs/v1.10/language/modules/syntax/#calling-a-child-module "Direct link to Calling a Child Module") --------------------------------------------------------------------------------------------------------------------------------------------------- To _call_ a module means to include the contents of that module into the configuration with specific values for its [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) . Modules are called from within other modules using `module` blocks: Code Block module "servers" { source = "./app-cluster" servers = 5} A module that includes a `module` block like this is the _calling module_ of the child module. The label immediately after the `module` keyword is a local name, which the calling module can use to refer to this instance of the module. Within the block body (between `{` and `}`) are the arguments for the module. Module calls use the following kinds of arguments: * The `source` argument is mandatory for all modules. * The `version` argument is recommended for modules from a registry. * Most other arguments correspond to [input variables](https://opentofu.org/docs/v1.10/language/values/variables/) defined by the module. (The `servers` argument in the example above is one of these.) * OpenTofu defines a few other meta-arguments that can be used with all modules, including `for_each` and `depends_on`. ### Source[​](https://opentofu.org/docs/v1.10/language/modules/syntax/#source "Direct link to Source") All modules **require** a `source` argument, which is a meta-argument defined by OpenTofu. Its value is either the path to a local directory containing the module's configuration files, or a remote module source that OpenTofu should download and use. For more information on possible values for this argument, see [Module Sources](https://opentofu.org/docs/v1.10/language/modules/sources/) . The same source address can be specified in multiple `module` blocks to create multiple copies of the resources defined within, possibly with different variable values. After adding, removing, or modifying `module` blocks, you must re-run `tofu init` to allow OpenTofu the opportunity to adjust the installed modules. By default this command will not upgrade an already-installed module; use the `-upgrade` option to instead upgrade to the newest available version. ### Version[​](https://opentofu.org/docs/v1.10/language/modules/syntax/#version "Direct link to Version") When using modules installed from a module registry, we recommend explicitly constraining the acceptable version numbers to avoid unexpected or unwanted changes. Use the `version` argument in the `module` block to specify versions: Code Block module "consul" { source = "hashicorp/consul/aws" version = "0.0.5" servers = 3} The `version` argument accepts a [version constraint string](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/) . OpenTofu will use the newest installed version of the module that meets the constraint; if no acceptable versions are installed, it will download the newest version that meets the constraint. Version constraints are supported only for modules installed from a module registry, such as the [Public OpenTofu Registry](https://registry.opentofu.org/) or any [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software) private modules registry. Other module sources can provide their own versioning mechanisms within the source string itself, or might not support versions at all. In particular, modules sourced from local file paths do not support `version`; since they're loaded from the same source repository, they always share the same version as their caller. ### Meta-arguments[​](https://opentofu.org/docs/v1.10/language/modules/syntax/#meta-arguments "Direct link to Meta-arguments") Along with `source` and `version`, OpenTofu defines a few more optional meta-arguments that have special meaning across all modules, described in more detail in the following pages: * `count` - Creates multiple instances of a module from a single `module` block. See [the `count` page](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) for details. * `for_each` - Creates multiple instances of a module from a single `module` block. See [the `for_each` page](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) for details. * `providers` - Passes provider configurations to a child module. See [the `providers` page](https://opentofu.org/docs/v1.10/language/meta-arguments/module-providers/) for details. If not specified, the child module inherits all of the default (un-aliased) provider configurations from the calling module. * `depends_on` - Creates explicit dependencies between the entire module and the listed targets. See [the `depends_on` page](https://opentofu.org/docs/v1.10/language/meta-arguments/depends_on/) for details. OpenTofu does not use the `lifecycle` argument. However, the `lifecycle` block is reserved for future versions. Accessing Module Output Values[​](https://opentofu.org/docs/v1.10/language/modules/syntax/#accessing-module-output-values "Direct link to Accessing Module Output Values") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The resources defined in a module are encapsulated, so the calling module cannot access their attributes directly. However, the child module can declare [output values](https://opentofu.org/docs/v1.10/language/values/outputs/) to selectively export certain values to be accessed by the calling module. For example, if the `./app-cluster` module referenced in the example above exported an output value named `instance_ids` then the calling module can reference that result using the expression `module.servers.instance_ids`: Code Block resource "aws_elb" "example" { # ... instances = module.servers.instance_ids} For more information about referring to named values, see [Expressions](https://opentofu.org/docs/v1.10/language/expressions/) . Transferring Resource State Into Modules[​](https://opentofu.org/docs/v1.10/language/modules/syntax/#transferring-resource-state-into-modules "Direct link to Transferring Resource State Into Modules") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Moving `resource` blocks from one module into several child modules causes OpenTofu to see the new location as an entirely different resource. As a result, OpenTofu plans to destroy all resource instances at the old address and create new instances at the new address. To preserve existing objects, you can use [refactoring blocks](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/) to record the old and new addresses for each resource instance. This directs OpenTofu to treat existing objects at the old addresses as if they had originally been created at the corresponding new addresses. Replacing resources within a module[​](https://opentofu.org/docs/v1.10/language/modules/syntax/#replacing-resources-within-a-module "Direct link to Replacing resources within a module") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ You may have an object that needs to be replaced with a new object for a reason that isn't automatically visible to OpenTofu, such as if a particular virtual machine is running on degraded underlying hardware. In this case, you can use [the `-replace=...` planning option](https://opentofu.org/docs/v1.10/cli/commands/plan/#replace-address) to force OpenTofu to propose replacing that object. If the object belongs to a resource within a nested module, specify the full path to that resource including all of the nested module steps leading to it. For example: Code Block $ tofu plan -replace=module.example.aws_instance.example The above selects a `resource "aws_instance" "example"` declared inside a `module "example"` child module declared inside your root module. Because replacing is a very disruptive action, OpenTofu only allows selecting individual resource instances. There is no syntax to force replacing _all_ resource instances belonging to a particular module. Removing a module[​](https://opentofu.org/docs/v1.10/language/modules/syntax/#removing-a-module "Direct link to Removing a module") ------------------------------------------------------------------------------------------------------------------------------------ The same as any `resource`, a `module` can be removed as well by using the `removed` refactoring block. When you remove the configuration of a module, OpenTofu will destroy all the resources that the removed module was managing. There are cases when the module is wanted to be removed from the configuration (and from the state) but the resources managed by it should stay untouched. To achieve this, follow these steps: 1. Delete the module from your configuration. 2. Add a removed block instead, specifying the module address you want to "forget" in the `from` attribute. 3. Specify the `lifecycle.destroy = false` Code Block removed { from = module.some_module lifecycle { destroy = false }} Note In contrast with `resource` blocks removal, `removed` blocks pointing to modules, do not allow usage of `provisioners`. * [Calling a Child Module](https://opentofu.org/docs/v1.10/language/modules/syntax/#calling-a-child-module) * [Source](https://opentofu.org/docs/v1.10/language/modules/syntax/#source) * [Version](https://opentofu.org/docs/v1.10/language/modules/syntax/#version) * [Meta-arguments](https://opentofu.org/docs/v1.10/language/modules/syntax/#meta-arguments) * [Accessing Module Output Values](https://opentofu.org/docs/v1.10/language/modules/syntax/#accessing-module-output-values) * [Transferring Resource State Into Modules](https://opentofu.org/docs/v1.10/language/modules/syntax/#transferring-resource-state-into-modules) * [Replacing resources within a module](https://opentofu.org/docs/v1.10/language/modules/syntax/#replacing-resources-within-a-module) * [Removing a module](https://opentofu.org/docs/v1.10/language/modules/syntax/#removing-a-module) --- # Sensitive Data in State | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/state/sensitive-data/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Sensitive Data in State ======================= OpenTofu state can contain sensitive data, depending on the resources in use and your definition of "sensitive." The state contains resource IDs and all resource attributes. For resources such as databases, this may contain initial passwords. When using local state, state is stored in plain-text JSON files. When using [remote state](https://opentofu.org/docs/v1.10/language/state/remote/) , state is only ever held in memory when used by OpenTofu. It may be encrypted at rest, but this depends on the specific remote state backend. Recommendations[​](https://opentofu.org/docs/v1.10/language/state/sensitive-data/#recommendations "Direct link to Recommendations") ------------------------------------------------------------------------------------------------------------------------------------ If you manage any sensitive data with OpenTofu (like database passwords, user passwords, or private keys), treat the state itself as sensitive data. Storing state remotely can provide better security. OpenTofu does not persist state to the local disk when remote state is in use, and some backends can be configured to encrypt the state data at rest. For example: * The S3 backend supports encryption at rest when the `encrypt` option is enabled. IAM policies and logging can be used to identify any invalid access. Requests for the state go over a TLS connection. * [Recommendations](https://opentofu.org/docs/v1.10/language/state/sensitive-data/#recommendations) --- # State Storage and Locking | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/state/backends/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page State Storage and Locking ========================= Backends are responsible for storing state and providing an API for [state locking](https://opentofu.org/docs/v1.10/language/state/locking/) . State locking is optional. Despite the state being stored remotely, all OpenTofu commands such as `tofu console`, the `tofu state` operations, `tofu taint`, and more will continue to work as if the state was local. State Storage[​](https://opentofu.org/docs/v1.10/language/state/backends/#state-storage "Direct link to State Storage") ------------------------------------------------------------------------------------------------------------------------ Backends determine where state is stored. For example, the local (default) backend stores state in a local JSON file on disk. The Consul backend stores the state within Consul. Both of these backends happen to provide locking: local via system APIs and Consul via locking APIs. When using a non-local backend, OpenTofu will not persist the state anywhere on disk except in the case of a non-recoverable error where writing the state to the backend failed. This behavior is a major benefit for backends: if sensitive values are in your state, using a remote backend allows you to use OpenTofu without that state ever being persisted to disk. In the case of an error persisting the state to the backend, OpenTofu will write the state locally. This is to prevent data loss. If this happens, the end user must manually push the state to the remote backend once the error is resolved. Manual State Pull/Push[​](https://opentofu.org/docs/v1.10/language/state/backends/#manual-state-pullpush "Direct link to Manual State Pull/Push") -------------------------------------------------------------------------------------------------------------------------------------------------- You can still manually retrieve the state from the remote state using the `tofu state pull` command. This will load your remote state and output it to stdout. You can choose to save that to a file or perform any other operations. You can also manually write state with `tofu state push`. **This is extremely dangerous and should be avoided if possible.** This will overwrite the remote state. This can be used to do manual fixups if necessary. When manually pushing state, OpenTofu will attempt to protect you from some potentially dangerous situations: * **Differing lineage**: The "lineage" is a unique ID assigned to a state when it is created. If a lineage is different, then it means the states were created at different times and its very likely you're modifying a different state. OpenTofu will not allow this. * **Higher serial**: Every state has a monotonically increasing "serial" number. If the destination state has a higher serial, OpenTofu will not allow you to write it since it means that changes have occurred since the state you're attempting to write. Both of these protections can be bypassed with the `-force` flag if you're confident you're making the right decision. Even if using the `-force` flag, we recommend making a backup of the state with `tofu state pull` prior to forcing the overwrite. State Locking[​](https://opentofu.org/docs/v1.10/language/state/backends/#state-locking "Direct link to State Locking") ------------------------------------------------------------------------------------------------------------------------ Backends are responsible for supporting [state locking](https://opentofu.org/docs/v1.10/language/state/locking/) if possible. Not all backends support locking. The [documentation for each backend](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#available-backends) includes details about whether it supports locking or not. For more information on state locking, view the [page dedicated to state locking](https://opentofu.org/docs/v1.10/language/state/locking/) . * [State Storage](https://opentofu.org/docs/v1.10/language/state/backends/#state-storage) * [Manual State Pull/Push](https://opentofu.org/docs/v1.10/language/state/backends/#manual-state-pullpush) * [State Locking](https://opentofu.org/docs/v1.10/language/state/backends/#state-locking) --- # Provider Requirements | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/providers/requirements/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provider Requirements ===================== OpenTofu relies on plugins called "providers" to interact with remote systems. OpenTofu configurations must declare which providers they require, so that OpenTofu can install and use them. This page documents how to declare providers so OpenTofu can install them. Additionally, some providers require configuration (like endpoint URLs or cloud regions) before they can be used. The [Provider Configuration](https://opentofu.org/docs/v1.10/language/providers/configuration/) page documents how to configure settings for providers. Requiring Providers[​](https://opentofu.org/docs/v1.10/language/providers/requirements/#requiring-providers "Direct link to Requiring Providers") -------------------------------------------------------------------------------------------------------------------------------------------------- Each module must declare which providers it requires, so that OpenTofu can install and use them. Provider requirements are declared in a `required_providers` block. A provider requirement consists of a local name, a source location, and a version constraint: Code Block terraform { required_providers { mycloud = { source = "mycorp/mycloud" version = "~> 1.0" } }} The `required_providers` block must be nested inside the top-level [`terraform` block](https://opentofu.org/docs/v1.10/language/settings/) (which can also contain other settings). Each argument in the `required_providers` block enables one provider. The key determines the provider's [local name](https://opentofu.org/docs/v1.10/language/providers/requirements/#local-names) (its unique identifier within this module), and the value is an object with the following elements: * `source` - the global [source address](https://opentofu.org/docs/v1.10/language/providers/requirements/#source-addresses) for the provider you intend to use, such as `hashicorp/aws`. * `version` - a [version constraint](https://opentofu.org/docs/v1.10/language/providers/requirements/#version-constraints) specifying which subset of available provider versions the module is compatible with. Names and Addresses[​](https://opentofu.org/docs/v1.10/language/providers/requirements/#names-and-addresses "Direct link to Names and Addresses") -------------------------------------------------------------------------------------------------------------------------------------------------- Each provider has two identifiers: * A unique _source address,_ which is only used when requiring a provider. * A _local name,_ which is used everywhere else in a module. ### Local Names[​](https://opentofu.org/docs/v1.10/language/providers/requirements/#local-names "Direct link to Local Names") Local names are module-specific, and are assigned when requiring a provider. Local names must be unique per-module. Outside of the `required_providers` block, OpenTofu configurations always refer to providers by their local names. For example, the following configuration declares `mycloud` as the local name for `mycorp/mycloud`, then uses that local name when [configuring the provider](https://opentofu.org/docs/v1.10/language/providers/configuration/) : Code Block terraform { required_providers { mycloud = { source = "mycorp/mycloud" version = "~> 1.0" } }}provider "mycloud" { # ...} Users of a provider can choose any local name for it. However, nearly every provider has a _preferred local name,_ which it uses as a prefix for all of its resource types. (For example, resources from `hashicorp/aws` all begin with `aws`, like `aws_instance` or `aws_security_group`.) Whenever possible, you should use a provider's preferred local name. This makes your configurations easier to understand, and lets you omit the `provider` meta-argument from most of your resources. (If a resource doesn't specify which provider configuration to use, OpenTofu interprets the first word of the resource type as a local provider name.) ### Source Addresses[​](https://opentofu.org/docs/v1.10/language/providers/requirements/#source-addresses "Direct link to Source Addresses") A provider's source address is its global identifier. It also specifies the primary location where OpenTofu can download it. Source addresses consist of three parts delimited by slashes (`/`), as follows: `[/]/` * **Hostname** (optional): The hostname of the registry that distributes the provider. If omitted, this defaults to `registry.opentofu.org`. * **Namespace:** An organizational namespace within the specified registry. In most cases this represents the organization that publishes the provider. This field may have other meanings for other registry hosts. * **Type:** A short name for the platform or system the provider manages. Must be unique within a particular namespace on a particular registry host. The type is usually the provider's preferred local name. (There are exceptions; for example, `hashicorp/google-beta` is an alternate release channel for `hashicorp/google`, so its preferred local name is `google`. If in doubt, check the provider's documentation.) For example, [the official HTTP provider](https://github.com/hashicorp/terraform-provider-http) belongs to the `hashicorp` namespace on `registry.opentofu.org`, so its source address is `registry.opentofu.org/hashicorp/http` or, more commonly, just `hashicorp/http`. The source address with all three components given explicitly is called the provider's _fully-qualified address_. You will see fully-qualified address in various outputs, like error messages, but in most cases a simplified display version is used. This display version omits the source host when it is the public registry, so you may see the shortened version `"hashicorp/random"` instead of `"registry.opentofu.org/hashicorp/random"`. Note If you omit the `source` argument when requiring a provider, OpenTofu uses an implied source address of `registry.opentofu.org/hashicorp/`. We recommend using explicit source addresses for all providers. ### Handling Local Name Conflicts[​](https://opentofu.org/docs/v1.10/language/providers/requirements/#handling-local-name-conflicts "Direct link to Handling Local Name Conflicts") Whenever possible, we recommend using a provider's preferred local name, which is usually the same as the "type" portion of its source address. However, it's sometimes necessary to use two providers with the same preferred local name in the same module, usually when the providers are named after a generic infrastructure type. OpenTofu requires unique local names for each provider in a module, so you'll need to use a non-preferred name for at least one of them. When this happens, we recommend combining each provider's namespace with its type name to produce compound local names with a dash: Code Block terraform { required_providers { # In the rare situation of using two providers that # have the same type name -- "http" in this example -- # use a compound local name to distinguish them. hashicorp-http = { source = "hashicorp/http" version = "~> 2.0" } mycorp-http = { source = "mycorp/http" version = "~> 1.0" } }}# References to these providers elsewhere in the# module will use these compound local names.provider "mycorp-http" { # ...}data "http" "example" { provider = hashicorp-http #...} OpenTofu won't be able to guess either provider's name from its resource types, so you'll need to specify a `provider` meta-argument for every affected resource. However, readers and maintainers of your module will be able to easily understand what's happening, and avoiding confusion is much more important than avoiding typing. Version Constraints[​](https://opentofu.org/docs/v1.10/language/providers/requirements/#version-constraints "Direct link to Version Constraints") -------------------------------------------------------------------------------------------------------------------------------------------------- Each provider plugin has its own set of available versions, allowing the functionality of the provider to evolve over time. Each provider dependency you declare should have a [version constraint](https://opentofu.org/docs/v1.10/language/expressions/version-constraints/) given in the `version` argument so OpenTofu can select a single version per provider that all modules are compatible with. The `version` argument is optional; if omitted, OpenTofu will accept any version of the provider as compatible. However, we strongly recommend specifying a version constraint for every provider your module depends on. To ensure OpenTofu always installs the same provider versions for a given configuration, you can use OpenTofu CLI to create a [dependency lock file](https://opentofu.org/docs/v1.10/language/files/dependency-lock/) and commit it to version control along with your configuration. If a lock file is present, OpenTofu CLI, and [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software) will all obey it when installing providers. ### Best Practices for Provider Versions[​](https://opentofu.org/docs/v1.10/language/providers/requirements/#best-practices-for-provider-versions "Direct link to Best Practices for Provider Versions") Each module should at least declare the minimum provider version it is known to work with, using the `>=` version constraint syntax: Code Block terraform { required_providers { mycloud = { source = "hashicorp/aws" version = ">= 1.0" } }} A module intended to be used as the root of a configuration β€”Β that is, as the directory where you'd run `tofu apply` β€”Β should also specify the _maximum_ provider version it is intended to work with, to avoid accidental upgrades to incompatible new versions. The `~>` operator is a convenient shorthand for allowing the rightmost component of a version to increment. The following example uses the operator to allow only patch releases within a specific minor release: Code Block terraform { required_providers { mycloud = { source = "hashicorp/aws" version = "~> 1.0.4" } }} Do not use `~>` (or other maximum-version constraints) for modules you intend to reuse across many configurations, even if you know the module isn't compatible with certain newer versions. Doing so can sometimes prevent errors, but more often it forces users of the module to update many modules simultaneously when performing routine upgrades. Specify a minimum version, document any known incompatibilities, and let the root module manage the maximum version. In-house Providers[​](https://opentofu.org/docs/v1.10/language/providers/requirements/#in-house-providers "Direct link to In-house Providers") ----------------------------------------------------------------------------------------------------------------------------------------------- Anyone can develop and distribute their own providers. Some organizations develop their own providers to configure proprietary systems, and wish to use these providers from OpenTofu without publishing them on a registry. One option for distributing such a provider is to run an in-house _private_ registry, by implementing [the provider registry protocol](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/) . Running an additional service just to distribute a single provider internally may be undesirable, so OpenTofu also supports [other provider installation methods](https://opentofu.org/docs/v1.10/cli/config/config-file/#provider-installation) , including placing provider plugins directly in specific directories in the local filesystem, via _filesystem mirrors_. All providers must have a [source address](https://opentofu.org/docs/v1.10/language/providers/requirements/#source-addresses) that includes (or implies) the hostname of a registry, but that hostname does not need to provide an actual registry service. For in-house providers that you intend to distribute from a local filesystem directory, you can use an arbitrary hostname in a domain your organization controls. For example, if your corporate domain were `example.com` then you might choose to use `tofu.example.com` as your placeholder hostname, even if that hostname doesn't actually resolve in DNS. You can then choose any namespace and type you wish to represent your in-house provider under that hostname, giving a source address like `tofu.example.com/examplecorp/ourcloud`: Code Block terraform { required_providers { mycloud = { source = "tofu.example.com/examplecorp/ourcloud" version = ">= 1.0" } }} To make version 1.0.0 of this provider available for installation from the local filesystem, choose one of the [implied local mirror directories](https://opentofu.org/docs/v1.10/cli/config/config-file/#implied-local-mirror-directories) and create a directory structure under it like this: Code Block tofu.example.com/examplecorp/ourcloud/1.0.0 Under that `1.0.0` directory, create one additional directory representing the platform where you are running OpenTofu, such as `linux_amd64` for Linux on an AMD64/x64 processor, and then place the provider plugin executable and any other needed files in that directory. Thus, on a Windows system, the provider plugin executable file might be at the following path: Code Block tofu.example.com/examplecorp/ourcloud/1.0.0/windows_amd64/tofu-provider-ourcloud.exe If you later decide to switch to using a real private provider registry rather than distribute binaries out of band, you can deploy the registry server at `tofu.example.com` and retain the same namespace and type names, in which case your existing modules will require no changes to locate the same provider using your registry server. * [Requiring Providers](https://opentofu.org/docs/v1.10/language/providers/requirements/#requiring-providers) * [Names and Addresses](https://opentofu.org/docs/v1.10/language/providers/requirements/#names-and-addresses) * [Local Names](https://opentofu.org/docs/v1.10/language/providers/requirements/#local-names) * [Source Addresses](https://opentofu.org/docs/v1.10/language/providers/requirements/#source-addresses) * [Handling Local Name Conflicts](https://opentofu.org/docs/v1.10/language/providers/requirements/#handling-local-name-conflicts) * [Version Constraints](https://opentofu.org/docs/v1.10/language/providers/requirements/#version-constraints) * [Best Practices for Provider Versions](https://opentofu.org/docs/v1.10/language/providers/requirements/#best-practices-for-provider-versions) * [In-house Providers](https://opentofu.org/docs/v1.10/language/providers/requirements/#in-house-providers) --- # Provisioners | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provisioners ============ You can use provisioners to model specific actions on the local machine or on a remote machine in order to prepare servers or other infrastructure objects for service. Provisioners are a Last Resort[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#provisioners-are-a-last-resort "Direct link to Provisioners are a Last Resort") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ OpenTofu includes the concept of provisioners as a measure of pragmatism, knowing that there are always certain behaviors that cannot be directly represented in OpenTofu's declarative model. However, they also add a considerable amount of complexity and uncertainty to OpenTofu usage. Firstly, OpenTofu cannot model the actions of provisioners as part of a plan because they can in principle take any action. Secondly, successful use of provisioners requires coordinating many more details than OpenTofu usage usually requires: direct network access to your servers, issuing OpenTofu credentials to log in, making sure that all of the necessary external software is installed, etc. The following sections describe some situations which can be solved with provisioners in principle, but where better solutions are also available. We do not recommend using provisioners for any of the use-cases described in the following sections. Even if your specific use-case is not described in the following sections, we still recommend attempting to solve it using other techniques first, and use provisioners only if there is no other option. ### Passing data into virtual machines and other compute resources[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#passing-data-into-virtual-machines-and-other-compute-resources "Direct link to Passing data into virtual machines and other compute resources") When deploying virtual machines or other similar compute resources, we often need to pass in data about other related infrastructure that the software on that server will need to do its job. The various provisioners that interact with remote servers over SSH or WinRM can potentially be used to pass such data by logging in to the server and providing it directly, but most cloud computing platforms provide mechanisms to pass data to instances at the time of their creation such that the data is immediately available on system boot. For example: * Alibaba Cloud: `user_data` on [`alicloud_instance`](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/instance) or [`alicloud_launch_template`](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/launch_template) . * Amazon EC2: `user_data` or `user_data_base64` on [`aws_instance`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) , [`aws_launch_template`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) , and [`aws_launch_configuration`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_configuration) . * Amazon Lightsail: `user_data` on [`aws_lightsail_instance`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lightsail_instance) . * Microsoft Azure: `custom_data` on [`azurerm_virtual_machine`](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_machine) or [`azurerm_virtual_machine_scale_set`](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_machine_scale_set) . * Google Cloud Platform: `metadata` on [`google_compute_instance`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance) or [`google_compute_instance_group`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance_group) . * Oracle Cloud Infrastructure: `metadata` or `extended_metadata` on [`oci_core_instance`](https://registry.terraform.io/providers/hashicorp/oci/latest/docs/resources/core_instance) or [`oci_core_instance_configuration`](https://registry.terraform.io/providers/hashicorp/oci/latest/docs/resources/core_instance_configuration) . * VMware vSphere: Attach a virtual CDROM to [`vsphere_virtual_machine`](https://registry.terraform.io/providers/hashicorp/vsphere/latest/docs/resources/virtual_machine) using the `cdrom` block, containing a file called `user-data.txt`. Many official Linux distribution disk images include software called [cloud-init](https://cloudinit.readthedocs.io/en/latest/) that can automatically process in various ways data passed via the means described above, allowing you to run arbitrary scripts and do basic system configuration immediately during the boot process and without the need to access the machine over SSH. If you are building custom machine images, you can make use of the "user data" or "metadata" passed by the above means in whatever way makes sense to your application, by referring to your vendor's documentation on how to access the data at runtime. This approach is _required_ if you intend to use any mechanism in your cloud provider for automatically launching and destroying servers in a group, because in that case individual servers will launch unattended while OpenTofu is not around to provision them. Even if you're deploying individual servers directly with OpenTofu, passing data this way will allow faster boot times and simplify deployment by avoiding the need for direct network access from OpenTofu to the new server and for remote access credentials to be provided. ### Provisioning files using cloud-config[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#provisioning-files-using-cloud-config "Direct link to Provisioning files using cloud-config") You can add the [`cloudinit_config`](https://registry.terraform.io/providers/hashicorp/cloudinit/latest/docs) data source to your OpenTofu configuration and specify the files you want to provision as `text/cloud-config` content. The `cloudinit_config` data source renders multi-part MIME configurations for use with [cloud-init](https://cloudinit.readthedocs.io/en/latest/) . Pass the files in the `content` field as YAML-encoded configurations using the `write_files` block. In the following example, the `my_cloud_config` data source specifies a `text/cloud-config` MIME part named `cloud.conf`. The `part.content` field is set to [`yamlencode`](https://opentofu.org/docs/v1.10/language/functions/yamlencode/) , which encodes the `write_files` JSON object as YAML so that the system can provision the referenced files. Code Block data "cloudinit_config" "my_cloud_config" { gzip = false base64_encode = false part { content_type = "text/cloud-config" filename = "cloud.conf" content = yamlencode( { "write_files" : [ { "path" : "/etc/foo.conf", "content" : "foo contents", }, { "path" : "/etc/bar.conf", "content" : file("bar.conf"), }, { "path" : "/etc/baz.conf", "content" : templatefile("baz.tpl.conf", { SOME_VAR = "qux" }), }, ], } ) }} ### Running configuration management software[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#running-configuration-management-software "Direct link to Running configuration management software") As a convenience to users who are forced to use generic operating system distribution images, OpenTofu includes a number of specialized provisioners for launching specific configuration management products. We strongly recommend not using these, and instead running system configuration steps during a custom image build process. For example, [HashiCorp Packer](https://www.packer.io/) offers a similar complement of configuration management provisioners and can run their installation steps during a separate build process, before creating a system disk image that you can deploy many times. If you are using configuration management software that has a centralized server component, you will need to delay the _registration_ step until the final system is booted from your custom image. To achieve that, use one of the mechanisms described above to pass the necessary information into each instance so that it can register itself with the configuration management server immediately on boot, without the need to accept commands from OpenTofu over SSH or WinRM. ### First-class provider functionality may be available[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#first-class-provider-functionality-may-be-available "Direct link to First-class provider functionality may be available") It is technically possible to use the `local-exec` provisioner to run the CLI for your target system in order to create, update, or otherwise interact with remote objects in that system. If you are trying to use a new feature of the remote system that isn't yet supported in its provider, that might be the only option. However, if there _is_ provider support for the feature you intend to use, prefer to use that provider functionality rather than a provisioner so that OpenTofu can be fully aware of the object and properly manage ongoing changes to it. Even if the functionality you need is not available in a provider today, we suggest to consider `local-exec` usage a temporary workaround and to also open an issue in the relevant provider's repository to discuss adding first-class provider support. Provider development teams often prioritize features based on interest, so opening an issue is a way to record your interest in the feature. Provisioners are used to execute scripts on a local or remote machine as part of resource creation or destruction. Provisioners can be used to bootstrap a resource, cleanup before destroy, run configuration management, etc. How to use Provisioners[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#how-to-use-provisioners "Direct link to How to use Provisioners") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- Note Provisioners should only be used as a last resort. For most common situations there are better alternatives. For more information, see the sections above. If you are certain that provisioners are the best way to solve your problem after considering the advice in the sections above, you can add a `provisioner` block inside the `resource` block of a compute instance. Code Block resource "aws_instance" "web" { # ... provisioner "local-exec" { command = "echo The server's IP address is ${self.private_ip}" }} The `local-exec` provisioner requires no other configuration, but most other provisioners must connect to the remote system using SSH or WinRM. You must include [a `connection` block](https://opentofu.org/docs/v1.10/language/resources/provisioners/connection/) so that OpenTofu knows how to communicate with the server. OpenTofu includes several built-in provisioners. You can also use third-party provisioners as plugins, by placing them in `%APPDATA%\terraform.d\plugins`, `~/.terraform.d/plugins`, `$XDG_DATA_HOME/opentofu/plugins`, or the same directory where the OpenTofu binary is installed. However, we do not recommend using any provisioners except the built-in `file`, `local-exec`, and `remote-exec` provisioners. All provisioners support the `when` and `on_failure` meta-arguments, which are described below (see [Destroy-Time Provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#destroy-time-provisioners) and [Failure Behavior](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#failure-behavior) ). ### The `self` Object[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#the-self-object "Direct link to the-self-object") Expressions in `provisioner` blocks cannot refer to their parent resource by name. Instead, they can use the special `self` object. The `self` object represents the provisioner's parent resource, and has all of that resource's attributes. For example, use `self.public_ip` to reference an `aws_instance`'s `public_ip` attribute. Technical note Resource references are restricted here because references create dependencies. Referring to a resource by name within its own block would create a dependency cycle. Suppressing Provisioner Logs in CLI Output[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#suppressing-provisioner-logs-in-cli-output "Direct link to Suppressing Provisioner Logs in CLI Output") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ The configuration for a `provisioner` block may use sensitive values, such as [`sensitive` variables](https://opentofu.org/docs/v1.10/language/values/variables/#suppressing-values-in-cli-output) or [`sensitive` output values](https://opentofu.org/docs/v1.10/language/values/outputs/#sensitive-suppressing-values-in-cli-output) . In this case, all log output from the provisioner is automatically suppressed to prevent the sensitive values from being displayed. Creation-Time Provisioners[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#creation-time-provisioners "Direct link to Creation-Time Provisioners") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ By default, provisioners run when the resource they are defined within is created. Creation-time provisioners are only run during _creation_, not during updating or any other lifecycle. They are meant as a means to perform bootstrapping of a system. If a creation-time provisioner fails, the resource is marked as **tainted**. A tainted resource will be planned for destruction and recreation upon the next `tofu apply`. OpenTofu does this because a failed provisioner can leave a resource in a semi-configured state. Because OpenTofu cannot reason about what the provisioner does, the only way to ensure proper creation of a resource is to recreate it. This is tainting. You can change this behavior by setting the `on_failure` attribute, which is covered in detail below. Destroy-Time Provisioners[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#destroy-time-provisioners "Direct link to Destroy-Time Provisioners") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If `when = destroy` is specified, the provisioner will run when the resource it is defined within is _destroyed_. Code Block resource "aws_instance" "web" { # ... provisioner "local-exec" { when = destroy command = "echo 'Destroy-time provisioner'" }} Destroy provisioners are run before the resource is destroyed. If they fail, OpenTofu will error and rerun the provisioners again on the next `tofu apply`. Due to this behavior, care should be taken for destroy provisioners to be safe to run multiple times. Note Destroy provisioners of this resource do not run if `create_before_destroy` is set to `true`. Destroy-time provisioners can only run if they remain in the configuration at the time a resource is destroyed. If a resource block with a destroy-time provisioner is removed entirely from the configuration, its provisioner configurations are removed along with it and thus the destroy provisioner won't run. To work around this, a multi-step process can be used to safely remove a resource with a destroy-time provisioner: * Update the resource configuration to include `count = 0`. * Apply the configuration to destroy any existing instances of the resource, including running the destroy provisioner. * Remove the resource block entirely from configuration, along with its `provisioner` blocks. * Apply again, at which point no further action should be taken since the resources were already destroyed. Because of this limitation, you should use destroy-time provisioners sparingly and with care. Note A destroy-time provisioner within a resource that is tainted _will not_ run. This includes resources that are marked tainted from a failed creation-time provisioner or tainted manually using `tofu taint`. Multiple Provisioners[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#multiple-provisioners "Direct link to Multiple Provisioners") --------------------------------------------------------------------------------------------------------------------------------------------------------------- Multiple provisioners can be specified within a resource. Multiple provisioners are executed in the order they're defined in the configuration file. You may also mix and match creation and destruction provisioners. Only the provisioners that are valid for a given operation will be run. Those valid provisioners will be run in the order they're defined in the configuration file. Example of multiple provisioners: Code Block resource "aws_instance" "web" { # ... provisioner "local-exec" { command = "echo first" } provisioner "local-exec" { command = "echo second" }} Failure Behavior[​](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#failure-behavior "Direct link to Failure Behavior") ------------------------------------------------------------------------------------------------------------------------------------------------ By default, provisioners that fail will also cause the OpenTofu apply itself to fail. The `on_failure` setting can be used to change this. The allowed values are: * `continue` - Ignore the error and continue with creation or destruction. * `fail` - Raise an error and stop applying (the default behavior). If this is a creation provisioner, taint the resource. Example: Code Block resource "aws_instance" "web" { # ... provisioner "local-exec" { command = "echo The server's IP address is ${self.private_ip}" on_failure = continue }} * [Provisioners are a Last Resort](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#provisioners-are-a-last-resort) * [Passing data into virtual machines and other compute resources](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#passing-data-into-virtual-machines-and-other-compute-resources) * [Provisioning files using cloud-config](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#provisioning-files-using-cloud-config) * [Running configuration management software](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#running-configuration-management-software) * [First-class provider functionality may be available](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#first-class-provider-functionality-may-be-available) * [How to use Provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#how-to-use-provisioners) * [The `self` Object](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#the-self-object) * [Suppressing Provisioner Logs in CLI Output](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#suppressing-provisioner-logs-in-cli-output) * [Creation-Time Provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#creation-time-provisioners) * [Destroy-Time Provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#destroy-time-provisioners) * [Multiple Provisioners](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#multiple-provisioners) * [Failure Behavior](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/#failure-behavior) --- # Debugging OpenTofu | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/internals/debugging/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Debugging OpenTofu ================== OpenTofu has detailed logs that you can enable by setting the `TF_LOG` environment variable to any value. Enabling this setting causes detailed logs to appear on `stderr`. You can set `TF_LOG` to one of the log levels (in order of decreasing verbosity) `TRACE`, `DEBUG`, `INFO`, `WARN` or `ERROR` to change the verbosity of the logs. Warning Logs produced with the `TRACE` level may contain sensitive details such as credentials and should be treated with care. Setting `TF_LOG` to `JSON` outputs logs at the `TRACE` level or higher, and uses a parseable JSON encoding as the formatting. Warning The JSON encoding of log files is not considered a stable interface. It may change at any time, without warning. It is meant to support tooling that will be forthcoming, and that tooling is the only supported way to interact with JSON formatted logs. Logging can be enabled separately for tofu itself and the provider plugins using the `TF_LOG_CORE` or `TF_LOG_PROVIDER` environment variables. These take the same level arguments as `TF_LOG`, but only activate a subset of the logs. To persist logged output you can set `TF_LOG_PATH` in order to force the log to always be appended to a specific file when logging is enabled. Note that even when `TF_LOG_PATH` is set, `TF_LOG` must be set in order for any logging to be enabled. If you find a bug with OpenTofu, please include the detailed log by using a service such as gist. --- # Getting started | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page What is OpenTofu? ================= OpenTofu is an infrastructure as code tool that lets you define both cloud and on-prem resources in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to provision and manage all of your infrastructure throughout its lifecycle. OpenTofu can manage low-level components like compute, storage, and networking resources, as well as high-level components like DNS entries and SaaS features. How does OpenTofu work?[​](https://opentofu.org/docs/v1.11/intro/#how-does-opentofu-work "Direct link to How does OpenTofu work?") ----------------------------------------------------------------------------------------------------------------------------------- OpenTofu creates and manages resources on cloud platforms and other services through their application programming interfaces (APIs). Providers enable OpenTofu to work with virtually any platform or service with an accessible API. The OpenTofu community have already written **thousands of providers** to manage many different types of resources and services. You can find all publicly available providers on the [Public OpenTofu Registry](https://github.com/opentofu/registry/tree/main/providers) , including Amazon Web Services (AWS), Azure, Google Cloud Platform (GCP), Kubernetes, Helm, GitHub, Splunk, DataDog, and many more. The core OpenTofu workflow consists of three stages: * **Write:** You define resources, which may be across multiple cloud providers and services. For example, you might create a configuration to deploy an application on virtual machines in a Virtual Private Cloud (VPC) network with security groups and a load balancer. * **Plan:** OpenTofu creates an execution plan describing the infrastructure it will create, update, or destroy based on the existing infrastructure and your configuration. * **Apply:** On approval, OpenTofu performs the proposed operations in the correct order, respecting any resource dependencies. For example, if you update the properties of a VPC and change the number of virtual machines in that VPC, OpenTofu will recreate the VPC before scaling the virtual machines. Why OpenTofu?[​](https://opentofu.org/docs/v1.11/intro/#why-opentofu "Direct link to Why OpenTofu?") ----------------------------------------------------------------------------------------------------- ### Manage any infrastructure[​](https://opentofu.org/docs/v1.11/intro/#manage-any-infrastructure "Direct link to Manage any infrastructure") Find providers for many of the platforms and services you already use in the [Public OpenTofu Registry](https://registry.opentofu.org/) . You can also use the [Terraform Plugin SDK](https://developer.hashicorp.com/terraform/plugin) to write your own. OpenTofu takes an [immutable approach to infrastructure](https://www.hashicorp.com/resources/what-is-mutable-vs-immutable-infrastructure) , reducing the complexity of upgrading or modifying your services and infrastructure. ### Track your infrastructure[​](https://opentofu.org/docs/v1.11/intro/#track-your-infrastructure "Direct link to Track your infrastructure") OpenTofu generates a plan and prompts you for your approval before modifying your infrastructure. It also keeps track of your real infrastructure in a [state file](https://opentofu.org/docs/v1.11/language/state/) , which acts as a source of truth for your environment. OpenTofu uses the state file to determine the changes to make to your infrastructure so that it will match your configuration. ### Automate changes[​](https://opentofu.org/docs/v1.11/intro/#automate-changes "Direct link to Automate changes") OpenTofu configuration files are declarative, meaning that they describe the end state of your infrastructure. You do not need to write step-by-step instructions to create resources because OpenTofu handles the underlying logic. OpenTofu builds a resource graph to determine resource dependencies and creates or modifies non-dependent resources in parallel. This allows OpenTofu to provision resources efficiently. ### Standardize configurations[​](https://opentofu.org/docs/v1.11/intro/#standardize-configurations "Direct link to Standardize configurations") OpenTofu supports reusable configuration components called [modules](https://opentofu.org/docs/v1.11/language/modules/) that define configurable collections of infrastructure, saving time and encouraging best practices. You can use publicly available modules from the OpenTofu Registry, or write your own. ### Collaborate[​](https://opentofu.org/docs/v1.11/intro/#collaborate "Direct link to Collaborate") Since your configuration is written in a file, you can commit it to a Version Control System (VCS) and use a cloud backend to efficiently manage OpenTofu workflows across teams. A cloud backend runs OpenTofu in a consistent, reliable environment and provides secure access to shared state and secret data, role-based access controls, a private registry for sharing both modules and providers, and more. Tip Learn more about [OpenTofu use cases](https://opentofu.org/docs/v1.11/intro/use-cases/) and [how OpenTofu compares to alternatives](https://opentofu.org/docs/v1.11/intro/vs/) . Community[​](https://opentofu.org/docs/v1.11/intro/#community "Direct link to Community") ------------------------------------------------------------------------------------------ We welcome questions, suggestions, and contributions from the community. * Ask questions in [OpenTofu Discuss](https://github.com/orgs/opentofu/discussions) . * Read our [contributing guide](https://github.com/opentofu/opentofu/blob/main/CONTRIBUTING.md) . * [Submit an issue](https://github.com/opentofu/opentofu/issues) for bugs and feature requests. * [How does OpenTofu work?](https://opentofu.org/docs/v1.11/intro/#how-does-opentofu-work) * [Why OpenTofu?](https://opentofu.org/docs/v1.11/intro/#why-opentofu) * [Manage any infrastructure](https://opentofu.org/docs/v1.11/intro/#manage-any-infrastructure) * [Track your infrastructure](https://opentofu.org/docs/v1.11/intro/#track-your-infrastructure) * [Automate changes](https://opentofu.org/docs/v1.11/intro/#automate-changes) * [Standardize configurations](https://opentofu.org/docs/v1.11/intro/#standardize-configurations) * [Collaborate](https://opentofu.org/docs/v1.11/intro/#collaborate) * [Community](https://opentofu.org/docs/v1.11/intro/#community) --- # Migrating to OpenTofu from Terraform | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/migration/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Migrating to OpenTofu from Terraform ==================================== Before you begin[​](https://opentofu.org/docs/v1.11/intro/migration/#before-you-begin "Direct link to Before you begin") ------------------------------------------------------------------------------------------------------------------------- OpenTofu aims to maintain compatibility with Terraform configurations. While most Terraform code will work without modification, we recommend following our [migration guide](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/) to ensure a smooth transition. Migration process overview[​](https://opentofu.org/docs/v1.11/intro/migration/#migration-process-overview "Direct link to Migration process overview") ------------------------------------------------------------------------------------------------------------------------------------------------------- The migration process is designed to be safe and reversible: 1. **Back up your infrastructure state and code** 2. **Install OpenTofu** 3. **Initialize and verify your configuration** 4. **Test with a small change** [β†’ Read the complete migration guide](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/) * [Before you begin](https://opentofu.org/docs/v1.11/intro/migration/#before-you-begin) * [Migration process overview](https://opentofu.org/docs/v1.11/intro/migration/#migration-process-overview) --- # Working with OpenTofu | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/core-workflow/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Working with OpenTofu ===================== The core OpenTofu workflow has three steps: 1. **Write** - Author infrastructure as code. 2. **Plan** - Preview changes before applying. 3. **Apply** - Provision reproducible infrastructure. This guide walks through how each of these three steps plays out in the context of working as an individual practitioner, how they evolve when a team is collaborating on infrastructure, and how a cloud backend enables this workflow to run smoothly for entire organizations. Working as an Individual Practitioner[​](https://opentofu.org/docs/v1.11/intro/core-workflow/#working-as-an-individual-practitioner "Direct link to Working as an Individual Practitioner") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Let's first walk through how these parts fit together as an individual working on infrastructure as code. ### Write[​](https://opentofu.org/docs/v1.11/intro/core-workflow/#write "Direct link to Write") You write OpenTofu configuration just like you write code: in your editor of choice. It's common practice to store your work in a version controlled repository even when you're just operating as an individual. Code Block # Create repository$ git init my-infra && cd my-infraInitialized empty Git repository in /.../my-infra/.git/# Write initial config$ vim main.tf# Initialize OpenTofu$ tofu initInitializing provider plugins...# ...OpenTofu has been successfully initialized! As you make progress on authoring your config, repeatedly running plans can help flush out syntax errors and ensure that your config is coming together as you expect. Code Block # Make edits to config$ vim main.tf# Review plan$ tofu plan# Make additional edits, and repeat$ vim main.tf This parallels working on application code as an individual, where a tight feedback loop between editing code and running test commands is useful. ### Plan[​](https://opentofu.org/docs/v1.11/intro/core-workflow/#plan "Direct link to Plan") When the feedback loop of the Write step has yielded a change that looks good, it's time to commit your work and review the final plan. Code Block $ git add main.tf$ git commit -m 'Managing infrastructure as code!'[main (root-commit) f735520] Managing infrastructure as code! 1 file changed, 1 insertion(+) Because `tofu apply` will display a plan for confirmation before proceeding to change any infrastructure, that's the command you run for final review. Code Block $ tofu applyAn execution plan has been generated and is shown below.# ... ### Apply[​](https://opentofu.org/docs/v1.11/intro/core-workflow/#apply "Direct link to Apply") After one last check, you are ready to tell OpenTofu to provision real infrastructure. Code Block Do you want to perform these actions? OpenTofu will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes# ...Apply complete! Resources: 1 added, 0 changed, 0 destroyed. At this point, it's common to push your version control repository to a remote location for safekeeping. Code Block $ git remote add origin https://github.com/*user*/*repo*.git$ git push origin main This core workflow is a loop; the next time you want to make changes, you start the process over from the beginning. Notice how closely this workflow parallels the process of writing application code or scripts as an individual? This is what we mean when we talk about OpenTofu enabling infrastructure as code. Working as a Team[​](https://opentofu.org/docs/v1.11/intro/core-workflow/#working-as-a-team "Direct link to Working as a Team") -------------------------------------------------------------------------------------------------------------------------------- Once multiple people are collaborating on OpenTofu configuration, new steps must be added to each part of the core workflow to ensure everyone is working together smoothly. You'll see that many of these steps parallel the workflow changes we make when we work on application code as teams rather than as individuals. ### Write[​](https://opentofu.org/docs/v1.11/intro/core-workflow/#write-1 "Direct link to Write") While each individual on a team still makes changes to OpenTofu configuration in their editor of choice, they save their changes to version control _branches_ to avoid colliding with each other's work. Working in branches enables team members to resolve mutually incompatible infrastructure changes using their normal merge conflict workflow. Code Block $ git checkout -b add-load-balancerSwitched to a new branch 'add-load-balancer' Running iterative plans is still useful as a feedback loop while authoring configuration, though having each team member's computer able to run them becomes more difficult with time. As the team and the infrastructure grows, so does the number of sensitive input variables (e.g. API Keys, SSL Cert Pairs) required to run a plan. To avoid the burden and the security risk of each team member arranging all sensitive inputs locally, it's common for teams to migrate to a model in which OpenTofu operations are executed in a shared Continuous Integration (CI) environment. The work needed to create such a CI environment is nontrivial, and is outside the scope of this core workflow overview. This longer iteration cycle of committing changes to version control and then waiting for the CI pipeline to execute is often lengthy enough to prohibit using speculative plans as a feedback loop while authoring individual OpenTofu configuration changes. Speculative plans are still useful before new OpenTofu changes are applied or even merged to the main development branch, however, as we'll see in a minute. ### Plan[​](https://opentofu.org/docs/v1.11/intro/core-workflow/#plan-1 "Direct link to Plan") For teams collaborating on infrastructure, OpenTofu's plan output creates an opportunity for team members to review each other's work. This allows the team to ask questions, evaluate risks, and catch mistakes before any potentially harmful changes are made. The natural place for these reviews to occur is alongside pull requests within version control--the point at which an individual proposes a merge from their working branch to the shared team branch. If team members review proposed config changes alongside speculative plan output, they can evaluate whether the intent of the change is being achieved by the plan. The problem becomes producing that speculative plan output for the team to review. Some teams that still run OpenTofu locally make a practice that pull requests should include an attached copy of speculative plan output generated by the change author. Others arrange for their CI system to post speculative plan output to pull requests automatically. In addition to reviewing the plan for the proper expression of its author's intent, the team can also make an evaluation whether they want this change to happen now. For example, if a team notices that a certain change could result in service disruption, they may decide to delay merging its pull request until they can schedule a maintenance window. ### Apply[​](https://opentofu.org/docs/v1.11/intro/core-workflow/#apply-1 "Direct link to Apply") Once a pull request has been approved and merged, it's important for the team to review the final concrete plan that's run against the shared team branch and the latest version of the state file. This plan has the potential to be different than the one reviewed on the pull request due to issues like merge order or recent infrastructural changes. For example, if a manual change was made to your infrastructure since the plan was reviewed, the plan might be different when you merge. It is at this point that the team asks questions about the potential implications of applying the change. Do we expect any service disruption from this change? Is there any part of this change that is high risk? Is there anything in our system that we should be watching as we apply this? Is there anyone we need to notify that this change is happening? Depending on the change, sometimes team members will want to watch the apply output as it is happening. For teams that are running OpenTofu locally, this may involve a screen share with the team. For teams running OpenTofu in CI, this may involve gathering around the build log. Just like the workflow for individuals, the core workflow for teams is a loop that plays out for each change. For some teams this loop happens a few times a week, for others, many times a day. Conclusion[​](https://opentofu.org/docs/v1.11/intro/core-workflow/#conclusion "Direct link to Conclusion") ----------------------------------------------------------------------------------------------------------- There are many different ways to use OpenTofu: as an individual user, a single team, or an entire organization at scale. Choosing the best approach for the density of collaboration needed will provide the most return on your investment in the core OpenTofu workflow. For organizations using OpenTofu at scale, [TACOS](https://opentofu.org/docs/v1.11/intro/tacos/) (TF Automation and Collaboration Software) introduces new layers that build on this core workflow to solve problems unique to teams and organizations. * [Working as an Individual Practitioner](https://opentofu.org/docs/v1.11/intro/core-workflow/#working-as-an-individual-practitioner) * [Write](https://opentofu.org/docs/v1.11/intro/core-workflow/#write) * [Plan](https://opentofu.org/docs/v1.11/intro/core-workflow/#plan) * [Apply](https://opentofu.org/docs/v1.11/intro/core-workflow/#apply) * [Working as a Team](https://opentofu.org/docs/v1.11/intro/core-workflow/#working-as-a-team) * [Write](https://opentofu.org/docs/v1.11/intro/core-workflow/#write-1) * [Plan](https://opentofu.org/docs/v1.11/intro/core-workflow/#plan-1) * [Apply](https://opentofu.org/docs/v1.11/intro/core-workflow/#apply-1) * [Conclusion](https://opentofu.org/docs/v1.11/intro/core-workflow/#conclusion) --- # Use Cases | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/use-cases/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Use Cases ========= [OpenTofu](https://opentofu.org/docs/v1.11/) is an infrastructure as code tool that lets you define infrastructure resources in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to safely and efficiently provision and manage your infrastructure throughout its lifecycle. This page describes popular OpenTofu use cases and provides related resources that you can use to create OpenTofu configurations and workflows. Multi-Cloud Deployment[​](https://opentofu.org/docs/v1.11/intro/use-cases/#multi-cloud-deployment "Direct link to Multi-Cloud Deployment") ------------------------------------------------------------------------------------------------------------------------------------------- Provisioning infrastructure across multiple clouds increases fault-tolerance, allowing for more graceful recovery from cloud provider outages. However, multi-cloud deployments add complexity because each provider has its own interfaces, tools, and workflows. OpenTofu lets you use the same workflow to manage multiple providers and handle cross-cloud dependencies. This simplifies management and orchestration for large-scale, multi-cloud infrastructures. ### Resources[​](https://opentofu.org/docs/v1.11/intro/use-cases/#resources "Direct link to Resources") * Use the [OpenTofu Registry Search](https://search.opentofu.org/) to discover and browse providers and modules with a user-friendly interface. This search tool is backed by the [Public OpenTofu Registry](https://github.com/opentofu/registry/) repository metadata. Application Infrastructure Deployment, Scaling, and Monitoring Tools[​](https://opentofu.org/docs/v1.11/intro/use-cases/#application-infrastructure-deployment-scaling-and-monitoring-tools "Direct link to Application Infrastructure Deployment, Scaling, and Monitoring Tools") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can use OpenTofu to efficiently deploy, release, scale, and monitor infrastructure for multi-tier applications. N-tier application architecture lets you scale application components independently and provides a separation of concerns. An application could consist of a pool of web servers that use a database tier, with additional tiers for API servers, caching servers, and routing meshes. OpenTofu allows you to manage the resources in each tier together, and automatically handles dependencies between tiers. For example, OpenTofu will deploy a database tier before provisioning the web servers that depend on it. Self-Service Clusters[​](https://opentofu.org/docs/v1.11/intro/use-cases/#self-service-clusters "Direct link to Self-Service Clusters") ---------------------------------------------------------------------------------------------------------------------------------------- At a large organization, your centralized operations team may get many repetitive infrastructure requests. You can use OpenTofu to build a "self-serve" infrastructure model that lets product teams manage their own infrastructure independently. You can create and use OpenTofu modules that codify the standards for deploying and managing services in your organization, allowing teams to efficiently deploy services in compliance with your organization’s practices. A cloud backend can also integrate with ticketing systems like ServiceNow to automatically generate new infrastructure requests. Policy Compliance and Management[​](https://opentofu.org/docs/v1.11/intro/use-cases/#policy-compliance-and-management "Direct link to Policy Compliance and Management") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu can help you enforce policies on the types of resources teams can provision and use. Ticket-based review processes are a bottleneck that can slow down development. Instead, you can use Sentinel, a policy-as-code framework, to automatically enforce compliance and governance policies before OpenTofu makes infrastructure changes. Sentinel policies are available in cloud backends. PaaS Application Setup[​](https://opentofu.org/docs/v1.11/intro/use-cases/#paas-application-setup "Direct link to PaaS Application Setup") ------------------------------------------------------------------------------------------------------------------------------------------- Platform as a Service (PaaS) vendors like Heroku allow you to create web applications and attach add-ons, such as databases or email providers. Heroku can elastically scale the number of dynos or workers, but most non-trivial applications need many add-ons and external services. You can use OpenTofu to codify the setup required for a Heroku application, configure a DNSimple to set a CNAME, and set up Cloudflare as a Content Delivery Network (CDN) for the app. OpenTofu can quickly and consistently do all of this without a web interface. Software Defined Networking[​](https://opentofu.org/docs/v1.11/intro/use-cases/#software-defined-networking "Direct link to Software Defined Networking") ---------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu can interact with Software Defined Networks (SDNs) to automatically configure the network according to the needs of the applications running in it. This lets you move from a ticket-based workflow to an automated one, reducing deployment times. Kubernetes[​](https://opentofu.org/docs/v1.11/intro/use-cases/#kubernetes "Direct link to Kubernetes") ------------------------------------------------------------------------------------------------------- Kubernetes is an open-source workload scheduler for containerized applications. OpenTofu lets you both deploy a Kubernetes cluster and manage its resources (e.g., pods, deployments, services, etc.). Parallel Environments[​](https://opentofu.org/docs/v1.11/intro/use-cases/#parallel-environments "Direct link to Parallel Environments") ---------------------------------------------------------------------------------------------------------------------------------------- You may have staging or QA environments that you use to test new applications before releasing them in production. As the production environment grows larger and more complex, it can be increasingly difficult to maintain an up-to-date environment for each stage of the development process. OpenTofu lets you rapidly spin up and decommission infrastructure for development, test, QA, and production. Using OpenTofu to create disposable environments as needed is more cost-efficient than maintaining each one indefinitely. Software Demos[​](https://opentofu.org/docs/v1.11/intro/use-cases/#software-demos "Direct link to Software Demos") ------------------------------------------------------------------------------------------------------------------- You can use OpenTofu to create, provision, and bootstrap a demo on various cloud providers. This lets end users easily try the software on their own infrastructure and even enables them to adjust parameters like cluster size to more rigorously test tools at any scale. * [Multi-Cloud Deployment](https://opentofu.org/docs/v1.11/intro/use-cases/#multi-cloud-deployment) * [Resources](https://opentofu.org/docs/v1.11/intro/use-cases/#resources) * [Application Infrastructure Deployment, Scaling, and Monitoring Tools](https://opentofu.org/docs/v1.11/intro/use-cases/#application-infrastructure-deployment-scaling-and-monitoring-tools) * [Self-Service Clusters](https://opentofu.org/docs/v1.11/intro/use-cases/#self-service-clusters) * [Policy Compliance and Management](https://opentofu.org/docs/v1.11/intro/use-cases/#policy-compliance-and-management) * [PaaS Application Setup](https://opentofu.org/docs/v1.11/intro/use-cases/#paas-application-setup) * [Software Defined Networking](https://opentofu.org/docs/v1.11/intro/use-cases/#software-defined-networking) * [Kubernetes](https://opentofu.org/docs/v1.11/intro/use-cases/#kubernetes) * [Parallel Environments](https://opentofu.org/docs/v1.11/intro/use-cases/#parallel-environments) * [Software Demos](https://opentofu.org/docs/v1.11/intro/use-cases/#software-demos) --- # Resource Importability | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/import/importability/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Resource Importability ====================== Each resource in OpenTofu must implement some basic logic to become importable. As a result, you cannot import all OpenTofu resources. Please reference the provider's specific documentation on which resources can be imported. If you have issues importing a resource, report an issue in the relevant provider repository. OpenTofu supports all providers through the Terraform Plugin SDK. To make a resource importable, refer to the [Terraform Plugin SDK Documentation](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/import) . --- # State Locking | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/state/locking/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page State Locking ============= If supported by your [backend](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) , OpenTofu will lock your state for all operations that could write state. This prevents others from acquiring the lock and potentially corrupting your state. State locking happens automatically on all operations that could write state. You won't see any message that it is happening. If state locking fails, OpenTofu will not continue. You can disable state locking for most commands with the `-lock` flag but it is not recommended. If acquiring the lock is taking longer than expected, OpenTofu will output a status message. If OpenTofu doesn't output a message, state locking is still occurring if your backend supports it. Not all backends support locking. The [documentation for each backend](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) includes details on whether it supports locking or not. Force Unlock[​](https://opentofu.org/docs/v1.10/language/state/locking/#force-unlock "Direct link to Force Unlock") -------------------------------------------------------------------------------------------------------------------- OpenTofu has a [force-unlock command](https://opentofu.org/docs/v1.10/cli/commands/force-unlock/) to manually unlock the state if unlocking failed. **Be very careful with this command.** If you unlock the state when someone else is holding the lock it could cause multiple writers. Force unlock should only be used to unlock your own lock in the situation where automatic unlocking failed. To protect you, the `force-unlock` command requires a unique lock ID. OpenTofu will output this lock ID if unlocking fails. This lock ID acts as a [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) , ensuring that locks and unlocks target the correct lock. * [Force Unlock](https://opentofu.org/docs/v1.10/language/state/locking/#force-unlock) --- # Plugin Signing | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/plugins/signing/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Plugin Signing ============== Note OpenTofu only authenticates provider plugins fetched from a registry. OpenTofu providers installed from the Registry are cryptographically signed and the signature is verified at time of installation. OpenTofu does **NOT** support fetching and using unsigned binaries, but you can manually install unsigned binaries. You should take extreme care when doing so as no programmatic authentication is performed. Environment Variables[​](https://opentofu.org/docs/v1.11/cli/plugins/signing/#environment-variables "Direct link to Environment Variables") -------------------------------------------------------------------------------------------------------------------------------------------- ### `OPENTOFU_ENFORCE_GPG_VALIDATION=false`[​](https://opentofu.org/docs/v1.11/cli/plugins/signing/#opentofu_enforce_gpg_validationfalse "Direct link to opentofu_enforce_gpg_validationfalse") A temporary change has been introduced to skip GPG validation under specific conditions: * **Registry Scope**: This change only affects provider packages from the default registry. * **Key Availability**: GPG validation will be skipped when and only when the provider's GPG keys are not available in the default registry. * **Temporary Measure**: This is a stopgap measure until GPG keys for all providers can be populated in the default registry. While this offers operational flexibility, it does reduce the level of security assurance for affected packages. Users who prioritize security should set the `OPENTOFU_ENFORCE_GPG_VALIDATION` environment variable to `true` to enforce GPG validation of all providers. **Future Removal**: We intend to remove this feature once all GPG keys are populated in the default registry, reverting to a strict GPG validation process for all providers. ### `OPENTOFU_ENFORCE_GPG_EXPIRATION=false`[​](https://opentofu.org/docs/v1.11/cli/plugins/signing/#opentofu_enforce_gpg_expirationfalse "Direct link to opentofu_enforce_gpg_expirationfalse") Many older keys present in the registry have expired and are no longer strictly valid. Historically, Terraform has not cared about the expiration date of keys in the registry and has ignored that field. When switching to a new crypto library, this functionality was made available. For legacy reasons, this is currently disabled by default (set to `false`), but may default to `true` in a future release as workflows are built into the registry for keeping keys up to date. * [Environment Variables](https://opentofu.org/docs/v1.11/cli/plugins/signing/#environment-variables) * [`OPENTOFU_ENFORCE_GPG_VALIDATION=false`](https://opentofu.org/docs/v1.11/cli/plugins/signing/#opentofu_enforce_gpg_validationfalse) * [`OPENTOFU_ENFORCE_GPG_EXPIRATION=false`](https://opentofu.org/docs/v1.11/cli/plugins/signing/#opentofu_enforce_gpg_expirationfalse) --- # Private Registries | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/private_registry/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Private Registries ================== OpenTofu, by default, uses the public registry at [registry.opentofu.org](https://registry.opentofu.org/) . However, organizations may have a need for a private registry for modules or providers that need to be kept private. There are several project that implement the [terraform registry API](https://developer.hashicorp.com/terraform/registry/api-docs) , aimed at providing this functionality of hosting a private registry. They are also compatible with OpenTofu. Some of the projects only support providers, some only support modules, and some support both. Choose one that is appropriate for your use case. List of Private Registries[​](https://opentofu.org/docs/v1.11/cli/private_registry/#list-of-private-registries "Direct link to List of Private Registries") ------------------------------------------------------------------------------------------------------------------------------------------------------------ The list of projects is available at [awesome-opentofu](https://github.com/virtualroot/awesome-opentofu?tab=readme-ov-file#registry) . How to Use[​](https://opentofu.org/docs/v1.11/cli/private_registry/#how-to-use "Direct link to How to Use") ------------------------------------------------------------------------------------------------------------ Follow the documentation provided by each registry to integrate it with your OpenTofu projects. * [List of Private Registries](https://opentofu.org/docs/v1.11/cli/private_registry/#list-of-private-registries) * [How to Use](https://opentofu.org/docs/v1.11/cli/private_registry/#how-to-use) --- # Server-side Login Protocol | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/internals/login-protocol/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Server-side Login Protocol ========================== Note You don't need to read these docs to _use_ [`tofu login`](https://opentofu.org/docs/v1.11/cli/commands/login/) . The information below is for anyone intending to implement the server side of `tofu login` in order to offer OpenTofu-native services in a third-party system. The `tofu login` command supports performing an OAuth 2.0 authorization request using configuration provided by the target host. You may wish to implement this protocol if you are producing a third-party implementation of any [OpenTofu-native services](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/) , such as an OpenTofu module registry. First, OpenTofu uses [remote service discovery](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/) to find the OAuth configuration for the host. The host must support the service name `login.v1` and define for it an object containing OAuth client configuration values, like this: Code Block { "login.v1": { "client": "tofu-cli", "grant_types": ["authz_code"], "authz": "/oauth/authorization", "token": "/oauth/token", "ports": [10000, 10010], }} The properties within the discovery object are as follows: * `client` (Required): The `client_id` value to use when making requests, as defined in [RFC 6749 section 2.2](https://tools.ietf.org/html/rfc6749#section-2.2) . Because OpenTofu is a _public client_ (it is installed on end-user systems and thus cannot protect an OAuth client secret), the `client_id` is purely advisory and the server must not use it as a guarantee that an authorization request is truly coming from OpenTofu. * `grant_types` (Optional): A JSON array of strings describing a set of OAuth 2.0 grant types the server is able to support. A "grant type" selects a specific mechanism by which an OAuth server authenticates the request and issues an authorization token. OpenTofu CLI supports a single grant type: * `authz_code`: [authorization code grant](https://tools.ietf.org/html/rfc6749#section-4.1) . Both the `authz` and `token` properties are required when `authz_code` is present. If not specified, `grant_types` defaults to `["authz_code"]`. * `authz` (Required if needed for a given grant type): the server's [authorization endpoint](https://tools.ietf.org/html/rfc6749#section-3.1) . If given as a relative URL, it is resolved from the location of the service discovery document. * `token` (Required if needed for a given grant type): the server's [token endpoint](https://tools.ietf.org/html/rfc6749#section-3.2) . If given as a relative URL, it is resolved from the location of the service discovery document. * `ports` (Optional): A two-element JSON array giving an inclusive range of TCP ports that OpenTofu may use for the temporary HTTP server it will start to provide the [redirection endpoint](https://tools.ietf.org/html/rfc6749#section-3.1.2) for the first step of an authorization code grant. OpenTofu opens a TCP listen port on the loopback interface in order to receive the response from the server's authorization endpoint. If not specified, OpenTofu is free to select any TCP port greater than or equal to 1024. OpenTofu allows constraining this port range for interoperability with OAuth server implementations that require each `client_id` to be associated with a fixed set of valid redirection endpoint URLs. Configure such a server to expect a range of URLs of the form `http://localhost:10000/` with different consecutive port numbers, and then specify that port range using `ports`. We recommend allowing at least 10 distinct port numbers if possible, and assigning them to numbers greater than or equal to 10000, to minimize the risk that all of the possible ports will already be in use on a particular system. When requesting an authorization code grant, OpenTofu CLI implements the [Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636) extension in order to protect against other applications on the system intercepting the incoming request to the redirection endpoint. We strongly recommend that you select an OAuth server implementation that also implements this extension and verifies the code challenge sent to the token endpoint. OpenTofu CLI does not support OAuth refresh tokens or token expiration. If your server issues time-limited tokens, OpenTofu CLI will simply begin receiving authorization errors once the token expires, after which the user can run `tofu login` again to obtain a new token. --- # Provider Metadata | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/internals/provider-meta/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provider Metadata ================= In some situations it's beneficial for a provider to offer an interface through which modules can pass it information unrelated to the resources in the module, but scoped on a per-module basis. Provider Metadata allows a provider to declare metadata fields it expects, which individual modules can then populate independently of any provider configuration. While provider configurations are often shared between modules, provider metadata is always module-specific. Provider Metadata is intended primarily for the situation where an official module is developed by the same vendor that produced the provider it is intended to work with, to allow the vendor to indirectly obtain usage statistics for each module via the provider. For that reason, this documentation is presented from the perspective of the provider developer rather than the module developer. Advanced Topic! This page covers technical details of OpenTofu. You don't need to understand these details to effectively use OpenTofu. The details are documented here for module authors and provider developers working on advanced functionality. Experimental Feature! This functionality is still considered experimental, and anyone taking advantage of it should [coordinate with the OpenTofu team](https://github.com/opentofu/opentofu/issues/new) to help the team understand how the feature is being used and to make sure their use case is taken into account as the feature develops. Defining the Schema[​](https://opentofu.org/docs/v1.11/internals/provider-meta/#defining-the-schema "Direct link to Defining the Schema") ------------------------------------------------------------------------------------------------------------------------------------------ Before a provider can receive information from a module, the provider must strictly define the data it can accept. You can do this by setting the `ProviderMeta` property on your `schema.Provider` struct. Its value functions similarly to the provider config: a map of strings to the `schema.Schema` describing the values those strings accept. Using the Data[​](https://opentofu.org/docs/v1.11/internals/provider-meta/#using-the-data "Direct link to Using the Data") --------------------------------------------------------------------------------------------------------------------------- When OpenTofu calls your provider, you can use the `schema.ResourceData` that your `Create`, `Read`, and `Update` functions already use to get access to the provider metadata being passed. First define a struct that matches your schema, then call the `GetProviderSchema` method on your `schema.ResourceData`, passing a pointer to a variable of that type. The variable will be populated with the provider metadata, and will return an error if there was an issue with parsing the data into the struct. Specifying Data in Modules[​](https://opentofu.org/docs/v1.11/internals/provider-meta/#specifying-data-in-modules "Direct link to Specifying Data in Modules") --------------------------------------------------------------------------------------------------------------------------------------------------------------- To include data in your modules, create a `provider_meta` nested block under your module's `terraform` block, with the name of the provider it's trying to pass information to: Code Block terraform { provider_meta "my-provider" { hello = "world" }} The `provider_meta` block must match the schema the provider has defined. Versioning Your Modules[​](https://opentofu.org/docs/v1.11/internals/provider-meta/#versioning-your-modules "Direct link to Versioning Your Modules") ------------------------------------------------------------------------------------------------------------------------------------------------------ Any module taking advantage of this functionality must make sure that the provider metadata supplied matches the schema defined in the provider, and that the version of OpenTofu that is being run has support for the provider metadata functionality. It's therefore recommended that any module taking advantage of this functionality should specify a minimum OpenTofu version of 0.13.0 or higher, and a minimum version of each of the providers it specifies metadata as the first version the schema being used was supported by the provider. * [Defining the Schema](https://opentofu.org/docs/v1.11/internals/provider-meta/#defining-the-schema) * [Using the Data](https://opentofu.org/docs/v1.11/internals/provider-meta/#using-the-data) * [Specifying Data in Modules](https://opentofu.org/docs/v1.11/internals/provider-meta/#specifying-data-in-modules) * [Versioning Your Modules](https://opentofu.org/docs/v1.11/internals/provider-meta/#versioning-your-modules) --- # What's new in OpenTofu 1.11? | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/whats-new/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page What's new in OpenTofu 1.11? ============================ New features[​](https://opentofu.org/docs/v1.11/intro/whats-new/#new-features "Direct link to New features") ------------------------------------------------------------------------------------------------------------- ### Ephemeral Resources / Write-Only Attributes[​](https://opentofu.org/docs/v1.11/intro/whats-new/#ephemeral-resources--write-only-attributes "Direct link to Ephemeral Resources / Write-Only Attributes") **Ephemeral values** allow OpenTofu to work with data and resources that exist only in memory during a single OpenTofu phase, guaranteeing that those values will not be persisted in state snapshots or plan files. You can now declare input variables and output values as being ephemeral, and you can use provider plugins that have been updated to include ephemeral resource types (e.g. for fetching a secret) or managed resource types with write-only attributes (e.g. for setting a password without saving it in OpenTofu state). For more information, refer to [Ephemerality](https://opentofu.org/docs/v1.11/language/ephemerality/) . ### Enabled meta-argument[​](https://opentofu.org/docs/v1.11/intro/whats-new/#enabled-meta-argument "Direct link to Enabled meta-argument") The new **`enabled` meta-argument** offers an alternative to the existing `count` and `for_each` meta-arguments for situations where a particular resource instance or module instance has either zero or one instances. The initial form of this argument is nested inside a `lifecycle` block, rather than directly inside a resource or module declaration, to avoid conflicting with existing input variables or resource type arguments named `enabled`. For more information, refer to [the `enabled` meta-argument](https://opentofu.org/docs/v1.11/language/meta-arguments/enabled/) . Improvements to existing features[​](https://opentofu.org/docs/v1.11/intro/whats-new/#improvements-to-existing-features "Direct link to Improvements to existing features") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### Tag support added to S3 backend[​](https://opentofu.org/docs/v1.11/intro/whats-new/#tag-support-added-to-s3-backend "Direct link to Tag support added to S3 backend") The S3 backend now supports **object tagging** your backend, allowing you to add custom tags to your state files for better organization and cost tracking. Deprecations[​](https://opentofu.org/docs/v1.11/intro/whats-new/#deprecations "Direct link to Deprecations") ------------------------------------------------------------------------------------------------------------- * **Azure Backend (`azurerm`)**: * The `endpoint` and `ARM_ENDPOINT` configuration options are no longer supported * The `msi_endpoint` and `ARM_MSI_ENDPOINT` options are no longer supported * The `environment` and `metadata_host` arguments are now mutually exclusive * **issensitive() Function**: Now correctly returns unknown results when evaluating unknown values. Code that previously relied on the incorrect behavior may need updates. * **Testing with Mocks**: Mock values generated during testing now strictly adhere to provider schemas. Test configurations with invalid mock values will need to be corrected. * **S3 Module Installation**: When installing module packages from Amazon S3 buckets using S3 source addresses OpenTofu will use the same credentials as the AWS CLI and SDK. * **TLS and SSH Security**: * SHA-1 signatures are no longer accepted for TLS or SSH connections * SSH certificates must comply with the `draft-miller-ssh-cert-03` specification Full Changelog[​](https://opentofu.org/docs/v1.11/intro/whats-new/#full-changelog "Direct link to Full Changelog") ------------------------------------------------------------------------------------------------------------------- You can find the full changelog at [https://github.com/opentofu/opentofu/blob/v1.11/CHANGELOG.md](https://github.com/opentofu/opentofu/blob/v1.11/CHANGELOG.md) * [New features](https://opentofu.org/docs/v1.11/intro/whats-new/#new-features) * [Ephemeral Resources / Write-Only Attributes](https://opentofu.org/docs/v1.11/intro/whats-new/#ephemeral-resources--write-only-attributes) * [Enabled meta-argument](https://opentofu.org/docs/v1.11/intro/whats-new/#enabled-meta-argument) * [Improvements to existing features](https://opentofu.org/docs/v1.11/intro/whats-new/#improvements-to-existing-features) * [Tag support added to S3 backend](https://opentofu.org/docs/v1.11/intro/whats-new/#tag-support-added-to-s3-backend) * [Deprecations](https://opentofu.org/docs/v1.11/intro/whats-new/#deprecations) * [Full Changelog](https://opentofu.org/docs/v1.11/intro/whats-new/#full-changelog) --- # Upgrading from OpenTofu 1.8.x/1.9.x/1.10.x | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/upgrading/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Upgrading from OpenTofu 1.8.x/1.9.x/1.10.x ========================================== OpenTofu 1.11.x is mostly compatible with previous OpenTofu versions. This migration guide will take you through the process of upgrading OpenTofu to version 1.11.0. Step 0: Prepare a disaster recovery plan[​](https://opentofu.org/docs/v1.11/intro/upgrading/#step-0-prepare-a-disaster-recovery-plan "Direct link to Step 0: Prepare a disaster recovery plan") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Although OpenTofu 1.11 is mostly compatible with previous versions, you should take the necessary precautions to prevent accidents. Make sure you have an up to date and _tested_ disaster recovery plan. Step 1: Apply all changes with OpenTofu 1.7.x/1.8.x/1.9.x[​](https://opentofu.org/docs/v1.11/intro/upgrading/#step-1-apply-all-changes-with-opentofu-17x18x19x "Direct link to Step 1: Apply all changes with OpenTofu 1.7.x/1.8.x/1.9.x") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Before proceeding, make sure that you apply all changes with `tofu apply`. Running `tofu plan` should result in no planned changes. While you can switch to OpenTofu with pending changes, it is not recommended. Code Block $ tofu plan...No changes. Your infrastructure matches the configuration.OpenTofu has compared your real infrastructure against yourconfiguration and found no differences, so no changes are needed. Step 2: Install OpenTofu 1.11.x[​](https://opentofu.org/docs/v1.11/intro/upgrading/#step-2-install-opentofu-111x "Direct link to Step 2: Install OpenTofu 1.11.x") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- As a first step, please [follow the installation instructions for the OpenTofu CLI tool](https://opentofu.org/docs/v1.11/intro/install/) . Please test if you can successfully execute the `tofu` command and receive the correct version: Code Block $ tofu --versionOpenTofu v1.11.0on linux_amd64 Step 3: Back up your state file[​](https://opentofu.org/docs/v1.11/intro/upgrading/#step-3-back-up-your-state-file "Direct link to Step 3: Back up your state file") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- Before you begin using the `tofu` binary on your Terraform code, make sure to back up your state file. If you are using a local state file, you can simply make a copy of your `terraform.tfstate` file in your project directory. If you are using a remote backend such as an S3 bucket, make sure that you follow the backup procedures for the backend and that you exercise the restore procedure at least once. Step 4: Initialize OpenTofu 1.11.x[​](https://opentofu.org/docs/v1.11/intro/upgrading/#step-4-initialize-opentofu-111x "Direct link to Step 4: Initialize OpenTofu 1.11.x") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Warning Should any of the following steps fail, please do not proceed and follow the [rollback instructions below](https://opentofu.org/docs/v1.11/intro/upgrading/#rolling-back-and-reporting-issues) instead. If you suspect the failure may be the result of a bug in OpenTofu, [please help us by opening an issue](https://github.com/opentofu/opentofu/issues) . Now you are ready to migrate. Run `tofu init` in the directory where your code resides. OpenTofu will download any providers and modules referenced in your configuration from the OpenTofu registry. Note If you are using the S3 backend - You will need to run `tofu init -reconfigure` to reinitialize the backend. Step 5: Inspect the plan[​](https://opentofu.org/docs/v1.11/intro/upgrading/#step-5-inspect-the-plan "Direct link to Step 5: Inspect the plan") ------------------------------------------------------------------------------------------------------------------------------------------------ Once initialized, run `tofu plan` and ensure that there are no pending changes similar to step 1 above. If there are unexpected changes in the plan, roll back to OpenTofu 1.8.x/1.9.x/1.10.x and troubleshoot your migration. (See the Troubleshooting section below.) Code Block $ tofu plan...No changes. Your infrastructure matches the configuration.OpenTofu has compared your real infrastructure against yourconfiguration and found no differences, so no changes are needed. Step 6: Test out a small change[​](https://opentofu.org/docs/v1.11/intro/upgrading/#step-6-test-out-a-small-change "Direct link to Step 6: Test out a small change") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- Before you begin using OpenTofu for larger changes, test out `tofu apply` with a smaller, non-critical change. Rolling back and reporting issues[​](https://opentofu.org/docs/v1.11/intro/upgrading/#rolling-back-and-reporting-issues "Direct link to Rolling back and reporting issues") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you have issues migrating to OpenTofu you can follow these steps to roll back to OpenTofu 1.8.x/1.9.x/1.10.x: 1. Create another backup of your state file. 2. Remove OpenTofu 1.11.x and verify that you are running OpenTofu 1.8.x/1.9.x/1.10.x. 3. Run `tofu init`. 4. Run `tofu plan` and verify that no unexpected changes are in the plan. 5. Test the rollback with a small, non-critical change. If you encountered a bug, [please report it on GitHub](https://github.com/opentofu/opentofu/issues) . Troubleshooting[​](https://opentofu.org/docs/v1.11/intro/upgrading/#troubleshooting "Direct link to Troubleshooting") ---------------------------------------------------------------------------------------------------------------------- If you encounter any issues during the migration to OpenTofu, you can join the [OpenTofu Slack](https://opentofu.org/slack/) or ask on [GitHub Discussions](https://github.com/orgs/opentofu/discussions) . ### Error: Failed to query available provider packages[​](https://opentofu.org/docs/v1.11/intro/upgrading/#error-failed-to-query-available-provider-packages "Direct link to Error: Failed to query available provider packages") This error happens when a provider you specified in your configuration is not available in the OpenTofu registry. Please roll back to OpenTofu 1.8.x/1.9.x/1.10.x and make sure your code works with that version. If your code works, please [submit an issue to include the provider in the registry](https://github.com/opentofu/registry/issues/) . ### Error: Module not found[​](https://opentofu.org/docs/v1.11/intro/upgrading/#error-module-not-found "Direct link to Error: Module not found") This error happens when a module you specified in your configuration is not available in the OpenTofu registry. Please roll back to OpenTofu 1.8.x/1.9.x/1.10.x and make sure your code works with that version. If your code works, please [submit an issue to include the module in the registry](https://github.com/opentofu/registry/issues/) . * [Step 0: Prepare a disaster recovery plan](https://opentofu.org/docs/v1.11/intro/upgrading/#step-0-prepare-a-disaster-recovery-plan) * [Step 1: Apply all changes with OpenTofu 1.7.x/1.8.x/1.9.x](https://opentofu.org/docs/v1.11/intro/upgrading/#step-1-apply-all-changes-with-opentofu-17x18x19x) * [Step 2: Install OpenTofu 1.11.x](https://opentofu.org/docs/v1.11/intro/upgrading/#step-2-install-opentofu-111x) * [Step 3: Back up your state file](https://opentofu.org/docs/v1.11/intro/upgrading/#step-3-back-up-your-state-file) * [Step 4: Initialize OpenTofu 1.11.x](https://opentofu.org/docs/v1.11/intro/upgrading/#step-4-initialize-opentofu-111x) * [Step 5: Inspect the plan](https://opentofu.org/docs/v1.11/intro/upgrading/#step-5-inspect-the-plan) * [Step 6: Test out a small change](https://opentofu.org/docs/v1.11/intro/upgrading/#step-6-test-out-a-small-change) * [Rolling back and reporting issues](https://opentofu.org/docs/v1.11/intro/upgrading/#rolling-back-and-reporting-issues) * [Troubleshooting](https://opentofu.org/docs/v1.11/intro/upgrading/#troubleshooting) * [Error: Failed to query available provider packages](https://opentofu.org/docs/v1.11/intro/upgrading/#error-failed-to-query-available-provider-packages) * [Error: Module not found](https://opentofu.org/docs/v1.11/intro/upgrading/#error-module-not-found) --- # Purpose of OpenTofu State | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/state/purpose/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Purpose of OpenTofu State ========================= State is a necessary requirement for OpenTofu to function. It is often asked if it is possible for OpenTofu to work without state, or for OpenTofu to not use state and just inspect real world resources on every run. This page will help explain why OpenTofu state is required. As you'll see from the reasons below, state is required. And in the scenarios where OpenTofu may be able to get away without state, doing so would require shifting massive amounts of complexity from one place (state) to another place (the replacement concept). Mapping to the Real World[​](https://opentofu.org/docs/v1.10/language/state/purpose/#mapping-to-the-real-world "Direct link to Mapping to the Real World") ----------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu requires some sort of database to map OpenTofu config to the real world. For example, when you have a resource `resource "aws_instance" "foo"` in your configuration, OpenTofu uses this mapping to know that the resource `resource "aws_instance" "foo"` represents a real world object with the instance ID `i-abcd1234` on a remote system. For some providers like AWS, OpenTofu could theoretically use something like AWS tags. Early prototypes of OpenTofu actually had no state files and used this method. However, we quickly ran into problems. The first major issue was a simple one: not all resources support tags, and not all cloud providers support tags. Therefore, for mapping configuration to resources in the real world, OpenTofu uses its own state structure. OpenTofu expects that each remote object is bound to only one resource instance in the configuration. If a remote object is bound to multiple resource instances, the mapping from configuration to the remote object in the state becomes ambiguous, and OpenTofu may behave unexpectedly. OpenTofu can guarantee a one-to-one mapping when it creates objects and records their identities in the state. When importing objects created outside of OpenTofu, you must make sure that each distinct object is imported to only one resource instance. Metadata[​](https://opentofu.org/docs/v1.10/language/state/purpose/#metadata "Direct link to Metadata") -------------------------------------------------------------------------------------------------------- Alongside the mappings between resources and remote objects, OpenTofu must also track metadata such as resource dependencies. OpenTofu typically uses the configuration to determine dependency order. However, when you delete a resource from an OpenTofu configuration, OpenTofu must know how to delete that resource from the remote system. OpenTofu can see that a mapping exists in the state file for a resource not in your configuration and plan to destroy. However, since the configuration no longer exists, the order cannot be determined from the configuration alone. To ensure correct operation, OpenTofu retains a copy of the most recent set of dependencies within the state. Now OpenTofu can still determine the correct order for destruction from the state when you delete one or more items from the configuration. One way to avoid this would be for OpenTofu to know a required ordering between resource types. For example, OpenTofu could know that servers must be deleted before the subnets they are a part of. The complexity for this approach quickly explodes, however: in addition to OpenTofu having to understand the ordering semantics of every resource for every _provider_, OpenTofu must also understand the ordering _across providers_. OpenTofu also stores other metadata for similar reasons, such as a pointer to the provider configuration that was most recently used with the resource in situations where multiple aliased providers are present. Performance[​](https://opentofu.org/docs/v1.10/language/state/purpose/#performance "Direct link to Performance") ----------------------------------------------------------------------------------------------------------------- In addition to basic mapping, OpenTofu stores a cache of the attribute values for all resources in the state. This is the most optional feature of OpenTofu state and is done only as a performance improvement. When running a `tofu plan`, OpenTofu must know the current state of resources in order to effectively determine the changes that it needs to make to reach your desired configuration. For small infrastructures, OpenTofu can query your providers and sync the latest attributes from all your resources. This is the default behavior of OpenTofu: for every plan and apply, OpenTofu will sync all resources in your state. For larger infrastructures, querying every resource is too slow. Many cloud providers do not provide APIs to query multiple resources at once, and the round trip time for each resource is hundreds of milliseconds. On top of this, cloud providers almost always have API rate limiting so OpenTofu can only request a certain number of resources in a period of time. Larger users of OpenTofu make heavy use of the `-refresh=false` flag as well as the `-target`/`-exclude` flags in order to work around this. In these scenarios, the cached state is treated as the record of truth. Syncing[​](https://opentofu.org/docs/v1.10/language/state/purpose/#syncing "Direct link to Syncing") ----------------------------------------------------------------------------------------------------- In the default configuration, OpenTofu stores the state in a file in the current working directory where OpenTofu was run. This is okay for getting started, but when using OpenTofu in a team it is important for everyone to be working with the same state so that operations will be applied to the same remote objects. [Remote state](https://opentofu.org/docs/v1.10/language/state/remote/) is the recommended solution to this problem. With a fully-featured state backend, OpenTofu can use remote locking as a measure to avoid two or more different users accidentally running OpenTofu at the same time, and thus ensure that each OpenTofu run begins with the most recent updated state. * [Mapping to the Real World](https://opentofu.org/docs/v1.10/language/state/purpose/#mapping-to-the-real-world) * [Metadata](https://opentofu.org/docs/v1.10/language/state/purpose/#metadata) * [Performance](https://opentofu.org/docs/v1.10/language/state/purpose/#performance) * [Syncing](https://opentofu.org/docs/v1.10/language/state/purpose/#syncing) --- # Backend Type: remote | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Backend Type: remote ==================== Most of the available backends provide different ways of storing state snapshots remotely. Therefore, they are often called remote state backends. This page describes a special `remote` backend, not to be confused with the simpler remote state backends. Note **We recommend using the [`cloud` built-in integration](https://opentofu.org/docs/v1.10/cli/cloud/settings/) ** instead of the `remote` backend. The `cloud` option includes an improved user experience and more features. The remote backend is unique among all other OpenTofu backends because it can both store state snapshots and execute CLI-driven run workflow operations for TF Automation and Collaboration Software ([TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) ) backends. It used to be called an "enhanced" backend. If your [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) provider enables full remote operations, you can execute commands such as `tofu plan` or `tofu apply` within the [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) runtime environment, with log output streaming directly to your local terminal. Remote plans and applies use variable values from the associated remote workspace. You can also use [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) with local operations, where only state is stored in the [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) remote backend. Command Support[​](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#command-support "Direct link to Command Support") ---------------------------------------------------------------------------------------------------------------------------------------- Note Features implementation might vary between different [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) . The remote backend supports the following OpenTofu commands: * `apply` * `console` * `destroy` * `fmt` * `get` * `graph` * `import` * `init` * `output` * `plan` * `providers` * `show` * `state` (supports all sub-commands: list, mv, pull, push, rm, show) * `taint` * `untaint` * `validate` * `version` * `workspace` Workspaces[​](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#workspaces "Direct link to Workspaces") ------------------------------------------------------------------------------------------------------------------------- The remote backend can work with either a single remote workspace, or with multiple similarly-named remote workspaces (like `networking-dev` and `networking-prod`). The `workspaces` block of the backend configuration determines which mode it uses: * To use a single remote workspace, set `workspaces.name` to the remote workspace's full name (like `networking-prod`). * To use multiple remote workspaces, set `workspaces.prefix` to a prefix used in all of the desired remote workspace names. For example, set `prefix = "networking-"` to use remote workspaces with names like `networking-dev` and `networking-prod`. This is helpful when mapping multiple OpenTofu CLI [workspaces](https://opentofu.org/docs/v1.10/language/state/workspaces/) used in a single OpenTofu configuration to multiple remote workspaces. The backend configuration requires either `name` or `prefix`. Omitting both or setting both results in a configuration error. If previous state is present when you run `tofu init` and the corresponding remote workspaces are empty or absent, OpenTofu will create workspaces and update the remote state accordingly. However, if your workspace requires variables or a specific version of OpenTofu for remote operations, we recommend that you create your remote workspaces on [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) before running any remote operations against them. ### Workspace Names[​](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#workspace-names "Direct link to Workspace Names") OpenTofu uses shortened names without the common prefix to interact with workspaces on the command line. For example, if `prefix = "networking-"`, use `tofu workspace select prod` to switch to the OpenTofu CLI workspace `prod` within the current configuration. However, remote OpenTofu operations such as `plan` and `apply` for that OpenTofu CLI workspace will take place in the remote workspace `networking-prod`. Because of this, the [`terraform.workspace`](https://opentofu.org/docs/v1.10/language/state/workspaces/#current-workspace-interpolation) interpolation expression produces different results depending on whether a remote workspace is configured to perform operations locally or remotely. For example, in a remote workspace calledΒ `networking-prod`Β created with `prefix = "networking-"` the expression produces the following: * For local operations, `terraform.workspace` =Β `prod` * For remote operations, `terraform.workspace`\= `networking-prod` Example Configurations[​](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#example-configurations "Direct link to Example Configurations") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Note We recommend omitting the token from the configuration, and instead using [`tofu login`](https://opentofu.org/docs/v1.10/cli/commands/login/) or manually configuring `credentials` in the [CLI config file](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials) . ### Basic Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#basic-configuration "Direct link to Basic Configuration") Code Block # Using a single workspace:terraform { backend "remote" { hostname = "app.example.io" organization = "company" workspaces { name = "my-app-prod" } }}# Using multiple workspaces:terraform { backend "remote" { hostname = "app.example.io" organization = "company" workspaces { prefix = "my-app-" } }} ### Using CLI Input[​](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#using-cli-input "Direct link to Using CLI Input") Code Block # main.tfterraform { required_version = "~> 0.12.0" backend "remote" {}} Backend configuration file: Code Block # config.remote.tfbackendworkspaces { name = "workspace" }hostname = "app.example.io"organization = "company" Running `tofu init` with the backend file: Code Block tofu init -backend-config=config.remote.tfbackend ### Data Source Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#data-source-configuration "Direct link to Data Source Configuration") Code Block data "terraform_remote_state" "foo" { backend = "remote" config = { organization = "company" workspaces = { name = "workspace" } }} Configuration Variables[​](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#configuration-variables "Direct link to Configuration Variables") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Warning We recommend using environment variables to supply credentials and other sensitive data. If you use `-backend-config` or hardcode these values directly in your configuration, OpenTofu will include these values in both the `.terraform` subdirectory and in plan files. Refer to [Credentials and Sensitive Data](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#credentials-and-sensitive-data) for details. The following configuration options are supported: * `hostname` - (Required) The remote backend hostname to connect to. * `organization` - (Required) The name of the organization containing the targeted workspace(s). * `token` - (Optional) The token used to authenticate with the remote backend. We recommend omitting the token from the configuration, and instead using [`tofu login`](https://opentofu.org/docs/v1.10/cli/commands/login/) or manually configuring `credentials` in the [CLI config file](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials) . * `workspaces` - (Required) A block specifying which remote workspace(s) to use. The `workspaces` block supports the following keys: * `name` - (Optional) The full name of one remote workspace. When configured, only the default workspace can be used. This option conflicts with `prefix`. * `prefix` - (Optional) A prefix used in the names of one or more remote workspaces, all of which can be used with this configuration. The full workspace names are used in [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) , and the short names (minus the prefix) are used on the command line for OpenTofu CLI workspaces. If omitted, only the default workspace can be used. This option conflicts with `name`. Note You must use the `name` key when configuring a `terraform_remote_state` data source that retrieves state from another remote workspace. The `prefix` key is only intended for use when configuring an instance of the remote backend. Command Line Arguments[​](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#command-line-arguments "Direct link to Command Line Arguments") ------------------------------------------------------------------------------------------------------------------------------------------------------------- For configurations that include a `backend "remote"` block, commands that make local modifications to OpenTofu state and then push them back up to the remote workspace accept the following option to modify that behavior: * `-ignore-remote-version` - Override checking that the local and remote OpenTofu versions agree, making an operation proceed even when there is a mismatch. Normally state-modification operations require using a local version of OpenTofu CLI which is compatible with the OpenTofu version selected for the remote workspace as part of its settings. This is to avoid the local operation creating a new state snapshot which the workspace's remote execution environment would then be unable to decode. Overriding this check can result in a remote workspace that is no longer able to complete remote operations, so we recommend against using this option. Excluding Files from Upload with .terraformignore[​](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#excluding-files-from-upload-with-terraformignore "Direct link to Excluding Files from Upload with .terraformignore") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When executing a remote `plan` or `apply` in a CLI-driven run, an archive of your configuration directory is uploaded to [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) . You can define paths to ignore from upload via a `.terraformignore` file at the root of your configuration directory. If this file is not present, the archive will exclude the following by default: * `.git/` directories * `.terraform/` directories (exclusive of `.terraform/modules`) The `.terraformignore` file can include rules as one would include in a [`.gitignore` file](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#_ignoring) * Comments (starting with `#`) or blank lines are ignored * End a pattern with a forward slash `/` to specify a directory * Negate a pattern by starting it with an exclamation point `!` Note that unlike `.gitignore`, only the `.terraformignore` at the root of the configuration directory is considered. * [Command Support](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#command-support) * [Workspaces](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#workspaces) * [Workspace Names](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#workspace-names) * [Example Configurations](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#example-configurations) * [Basic Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#basic-configuration) * [Using CLI Input](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#using-cli-input) * [Data Source Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#data-source-configuration) * [Configuration Variables](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#configuration-variables) * [Command Line Arguments](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#command-line-arguments) * [Excluding Files from Upload with .terraformignore](https://opentofu.org/docs/v1.10/language/settings/backends/remote/#excluding-files-from-upload-with-terraformignore) --- # Initializing Working Directories | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/init/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Initializing Working Directories ================================ OpenTofu expects to be invoked from a working directory that contains configuration files written in [the OpenTofu language](https://opentofu.org/docs/v1.11/language/) . OpenTofu uses configuration content from this directory, and also uses the directory to store settings, cached plugins and modules, and sometimes state data. A working directory must be initialized before OpenTofu can perform any operations in it (like provisioning infrastructure or modifying state). Working Directory Contents[​](https://opentofu.org/docs/v1.11/cli/init/#working-directory-contents "Direct link to Working Directory Contents") ------------------------------------------------------------------------------------------------------------------------------------------------ A OpenTofu working directory typically contains: * A OpenTofu configuration describing resources OpenTofu should manage. This configuration is expected to change over time. * A hidden `.terraform` directory, which OpenTofu uses to manage cached provider plugins and modules, record which [workspace](https://opentofu.org/docs/v1.11/cli/workspaces/) is currently active, and record the last known backend configuration in case it needs to migrate state on the next run. This directory is automatically managed by OpenTofu, and is created during initialization. * State data, if the configuration uses the default `local` backend. This is managed by OpenTofu in a `terraform.tfstate` file (if the directory only uses the default workspace) or a `terraform.tfstate.d` directory (if the directory uses multiple workspaces). Initialization[​](https://opentofu.org/docs/v1.11/cli/init/#initialization "Direct link to Initialization") ------------------------------------------------------------------------------------------------------------ Run the `tofu init` command to initialize a working directory that contains a OpenTofu configuration. After initialization, you will be able to perform other commands, like `tofu plan` and `tofu apply`. If you try to run a command that relies on initialization without first initializing, the command will fail with an error and explain that you need to run init. Initialization performs several tasks to prepare a directory, including accessing state in the configured backend, downloading and installing provider plugins, and downloading modules. Under some conditions (usually when changing from one backend to another), it might ask the user for guidance or confirmation. For details, see [the `tofu init` command](https://opentofu.org/docs/v1.11/cli/commands/init/) . Reinitialization[​](https://opentofu.org/docs/v1.11/cli/init/#reinitialization "Direct link to Reinitialization") ------------------------------------------------------------------------------------------------------------------ Certain types of changes to a OpenTofu configuration can require reinitialization before normal operations can continue. This includes changes to provider requirements, module sources or version constraints, and backend configurations. You can reinitialize a directory by running `tofu init` again. In fact, you can reinitialize at any time; the init command is idempotent, and will have no effect if no changes are required. If reinitialization is required, any commands that rely on initialization will fail with an error and tell you so. Reinitializing Only Modules[​](https://opentofu.org/docs/v1.11/cli/init/#reinitializing-only-modules "Direct link to Reinitializing Only Modules") --------------------------------------------------------------------------------------------------------------------------------------------------- The `tofu get` command will download modules referenced in the configuration, but will not perform the other required initialization tasks. This command is only useful for niche workflows, and most OpenTofu users can ignore it in favor of `tofu init`. * [Working Directory Contents](https://opentofu.org/docs/v1.11/cli/init/#working-directory-contents) * [Initialization](https://opentofu.org/docs/v1.11/cli/init/#initialization) * [Reinitialization](https://opentofu.org/docs/v1.11/cli/init/#reinitialization) * [Reinitializing Only Modules](https://opentofu.org/docs/v1.11/cli/init/#reinitializing-only-modules) --- # Functions Metadata | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/internals/functions-meta/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Functions Metadata ================== The `tofu metadata functions` command is used to print signatures for the functions available in the current OpenTofu version. Usage[​](https://opentofu.org/docs/v1.11/internals/functions-meta/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------- Usage: `tofu metadata functions [options]` The following flags are available: * `-json` - Displays the function signatures in a machine-readable, JSON format. Please note that, at this time, the `-json` flag is a _required_ option. In future releases, this command will be extended to allow for additional options. The output includes a `format_version` key, which has value `"1.0"`. The semantics of this version are: * We will increment the minor version, e.g. `"1.1"`, for backward-compatible changes or additions. Ignore any object properties with unrecognized names to remain forward-compatible with future minor versions. * We will increment the major version, e.g. `"2.0"`, for changes that are not backward-compatible. Reject any input which reports an unsupported major version. We will introduce new major versions only within the bounds of [the OpenTofu 1.0 Compatibility Promises](https://opentofu.org/docs/v1.11/language/v1-compatibility-promises/) . Format Summary[​](https://opentofu.org/docs/v1.11/internals/functions-meta/#format-summary "Direct link to Format Summary") ---------------------------------------------------------------------------------------------------------------------------- The following sections describe the JSON output format by example, using a pseudo-JSON notation. Important elements are described with comments, which are prefixed with `//`. To avoid excessive repetition, we've split the complete format into several discrete sub-objects, described under separate headers. References wrapped in angle brackets (like ``) are placeholders which, in the real output, would be replaced by an instance of the specified sub-object. The JSON output format consists of the following objects and sub-objects: * [Function Signature Representation](https://opentofu.org/docs/v1.11/internals/functions-meta/#function-signature-representation) - the top-level object returned by `tofu metadata functions -json` * [Parameter Representation](https://opentofu.org/docs/v1.11/internals/functions-meta/#parameter-representation) - a sub-object of signatures that describes their parameters Function Signature Representation[​](https://opentofu.org/docs/v1.11/internals/functions-meta/#function-signature-representation "Direct link to Function Signature Representation") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block { "format_version": "1.0", // "function_signatures" describes the signatures for all // available functions. "function_signatures": { // keys in this map are the function names, such as "abs" "example_function": { // "description" is an English-language description of // the purpose and usage of the function in Markdown. "description": "string", // "return_type" is a representation of a type specification // that the function returns. "return_type": "string", // "parameters" is an optional list of the positional parameters // that the function accepts. "parameters": [ , … ], // "variadic_parameter" is an optional representation of the // additional arguments that the function accepts after those // matching with the fixed parameters. "variadic_parameter": }, "example_function_two": { … } }} Parameter Representation[​](https://opentofu.org/docs/v1.11/internals/functions-meta/#parameter-representation "Direct link to Parameter Representation") ---------------------------------------------------------------------------------------------------------------------------------------------------------- A parameter representation describes a parameter to a function. Code Block { // "name" is the internal name of the parameter "name": "string", // "description" is an optional English-language description of // the purpose and usage of the parameter in Markdown. "description": "string", // "type" is a representation of a type specification // that the parameter's value must conform to. "type": "string"} * [Usage](https://opentofu.org/docs/v1.11/internals/functions-meta/#usage) * [Format Summary](https://opentofu.org/docs/v1.11/internals/functions-meta/#format-summary) * [Function Signature Representation](https://opentofu.org/docs/v1.11/internals/functions-meta/#function-signature-representation) * [Parameter Representation](https://opentofu.org/docs/v1.11/internals/functions-meta/#parameter-representation) --- # OpenTofu vs. Alternatives | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/vs/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu vs. Alternatives ========================= OpenTofu provides a flexible abstraction of resources and providers. This model allows for representing everything from physical hardware, virtual machines, and containers, to email and DNS providers. Because of this flexibility, OpenTofu can be used to solve many different problems. This means there are a number of existing tools that overlap with the capabilities of OpenTofu. We compare OpenTofu to a number of these tools, but it should be noted that OpenTofu is not mutually exclusive with other systems. It can be used to manage a single application, or the entire datacenter. Learn how OpenTofu compares to: * [Chef, Puppet, etc.](https://opentofu.org/docs/v1.11/intro/vs/chef-puppet/) * [CloudFormation, Heat, etc.](https://opentofu.org/docs/v1.11/intro/vs/cloudformation/) * [Custom Solutions](https://opentofu.org/docs/v1.11/intro/vs/custom/) * [Boto, Fog, etc.](https://opentofu.org/docs/v1.11/intro/vs/boto/) * [Terraform](https://opentofu.org/faq/#opentofu-terraform-differences) --- # OpenTofu vs. Boto, Fog, etc. | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/vs/boto/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu vs. Boto, Fog, etc. ============================ Libraries like Boto, Fog, etc. are used to provide native access to cloud providers and services by using their APIs. Some libraries are focused on specific clouds, while others attempt to bridge them all and mask the semantic differences. Using a client library only provides low-level access to APIs, requiring application developers to create their own tooling to build and manage their infrastructure. OpenTofu is not intended to give low-level programmatic access to providers, but instead provides a high level syntax for describing how cloud resources and services should be created, provisioned, and combined. OpenTofu is very flexible, using a plugin-based model to support providers and provisioners, giving it the ability to support almost any service that exposes APIs. --- # OpenTofu vs. Custom Solutions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/vs/custom/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu vs. Custom Solutions ============================= Most organizations start by manually managing infrastructure through simple scripts or web-based interfaces. As the infrastructure grows, any manual approach to management becomes both error-prone and tedious, and many organizations begin to home-roll tooling to help automate the mechanical processes involved. These tools require time and resources to build and maintain. As tools of necessity, they represent the minimum viable features needed by an organization, being built to handle only the immediate needs. As a result, they are often hard to extend and difficult to maintain. Because the tooling must be updated in lockstep with any new features or infrastructure, it becomes the limiting factor for how quickly the infrastructure can evolve. OpenTofu is designed to tackle these challenges. It provides a simple, unified syntax, allowing almost any resource to be managed without learning new tooling. By capturing all the resources required, the dependencies between them can be resolved automatically so that operators do not need to remember and reason about them. Removing the burden of building the tool allows operators to focus on their infrastructure and not the tooling. Furthermore, OpenTofu is an open source tool. The community around OpenTofu helps to extend its features, fix bugs and document new use cases. OpenTofu helps solve a problem that exists in every organization and provides a standard that can be adopted to avoid reinventing the wheel between and within organizations. Its open source nature ensures it will be around in the long term. --- # OpenTofu vs. Chef, Puppet, etc. | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/vs/chef-puppet/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu vs. Chef, Puppet, etc. =============================== Configuration management tools install and manage software on a machine that already exists. OpenTofu is not a configuration management tool, and it allows existing tooling to focus on their strengths: bootstrapping and initializing resources. OpenTofu focuses on the higher-level abstraction of the datacenter and associated services, while allowing you to use configuration management tools on individual systems. It also aims to bring the same benefits of codification of your system configuration to infrastructure management. If you are using traditional configuration management within your compute instances, you can use OpenTofu to configure bootstrapping software like cloud-init to activate your configuration management software on first system boot. --- # Migration Guide | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Migration Guide =============== This guide walks you through migrating from Terraform to OpenTofu. It is designed to be safe and reversible, allowing you to test OpenTofu without disrupting your existing infrastructure. Prerequisites[​](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#prerequisites "Direct link to Prerequisites") -------------------------------------------------------------------------------------------------------------------------------- * An existing Terraform configuration * Access to your Terraform state files * Ability to run both `terraform` and `tofu` commands during the migration Step 1: Back up your infrastructure[​](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#step-1-back-up-your-infrastructure "Direct link to Step 1: Back up your infrastructure") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Before starting the migration, create backups of: 1. **Your Terraform state files** * For local state: Copy your `terraform.tfstate` and `terraform.tfstate_backup` files * For remote state: Follow your backend's backup procedures (e.g., S3 versioning, snapshot your state bucket) 2. **Your Terraform configuration files** * Commit all changes to version control * Consider creating a migration branch Step 2: Install OpenTofu[​](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#step-2-install-opentofu "Direct link to Step 2: Install OpenTofu") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Follow the [installation guide](https://opentofu.org/docs/intro/install/) to install OpenTofu on your system. Verify the installation: Code Block tofu --version Step 3: Initialize OpenTofu[​](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#step-3-initialize-opentofu "Direct link to Step 3: Initialize OpenTofu") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- In your Terraform project directory, initialize OpenTofu: Code Block tofu init This command will: * Download required providers from the OpenTofu registry * Initialize your backend configuration * Prepare your working directory Step 4: Verify your configuration[​](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#step-4-verify-your-configuration "Direct link to Step 4: Verify your configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Run a plan to ensure OpenTofu can read your state and configuration: Code Block tofu plan **Expected result**: You should see "No changes" or the same plan output you would see with Terraform. If you see unexpected changes: 1. Do not apply the changes 2. Investigate the differences 3. Consider rolling back (see below) Step 5: Apply with OpenTofu[​](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#step-5-apply-with-opentofu "Direct link to Step 5: Apply with OpenTofu") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Once you've verified the plan shows no unexpected changes, run: Code Block tofu apply Even if there are no infrastructure changes, this ensures OpenTofu updates the state file format if needed. Step 6: Test with a small change[​](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#step-6-test-with-a-small-change "Direct link to Step 6: Test with a small change") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Make a small, non-critical change to your configuration (e.g., add a tag to a resource) and run: Code Block tofu plantofu apply This verifies that OpenTofu can successfully manage your infrastructure going forward. Rolling back to Terraform[​](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#rolling-back-to-terraform "Direct link to Rolling back to Terraform") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you encounter issues during migration, you can safely roll back: 1. **Stop using OpenTofu immediately** 2. **Restore from your backups** (if any state changes were made) 3. **Run Terraform commands**: Code Block terraform initterraform plan 4. **Verify no unexpected changes** appear in the plan 5. **Continue using Terraform** as before Getting help[​](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#getting-help "Direct link to Getting help") ----------------------------------------------------------------------------------------------------------------------------- If you encounter issues during migration: * Join the [OpenTofu Slack](https://opentofu.org/slack/) * Ask on [GitHub Discussions](https://github.com/orgs/opentofu/discussions) * Report bugs on [GitHub Issues](https://github.com/opentofu/opentofu/issues) * [Prerequisites](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#prerequisites) * [Step 1: Back up your infrastructure](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#step-1-back-up-your-infrastructure) * [Step 2: Install OpenTofu](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#step-2-install-opentofu) * [Step 3: Initialize OpenTofu](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#step-3-initialize-opentofu) * [Step 4: Verify your configuration](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#step-4-verify-your-configuration) * [Step 5: Apply with OpenTofu](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#step-5-apply-with-opentofu) * [Step 6: Test with a small change](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#step-6-test-with-a-small-change) * [Rolling back to Terraform](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#rolling-back-to-terraform) * [Getting help](https://opentofu.org/docs/v1.11/intro/migration/migration-guide/#getting-help) --- # Remote State | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/state/remote/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Remote State ============ By default, OpenTofu stores state locally in a file named `terraform.tfstate`. When working with OpenTofu in a team, use of a local file makes OpenTofu usage complicated because each user must make sure they always have the latest state data before running OpenTofu and make sure that nobody else runs OpenTofu at the same time. With _remote_ state, OpenTofu writes the state data to a remote data store, which can then be shared between all members of a team. OpenTofu supports storing state in [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software), [HashiCorp Consul](https://www.consul.io/) , Amazon S3, Azure Blob Storage, Google Cloud Storage, Alibaba Cloud OSS, and more. Remote state is implemented by a [backend](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) or by [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software), both of which you can configure in your configuration's root module. Delegation and Teamwork[​](https://opentofu.org/docs/v1.10/language/state/remote/#delegation-and-teamwork "Direct link to Delegation and Teamwork") ---------------------------------------------------------------------------------------------------------------------------------------------------- Remote state allows you to share [output values](https://opentofu.org/docs/v1.10/language/values/outputs/) with other configurations. This allows your infrastructure to be decomposed into smaller components. Put another way, remote state also allows teams to share infrastructure resources in a read-only way without relying on any additional configuration store. For example, a core infrastructure team can handle building the core machines, networking, etc. and can expose some information to other teams to run their own infrastructure. As a more specific example with AWS: you can expose things such as VPC IDs, subnets, NAT instance IDs, etc. through remote state and have other OpenTofu states consume that. For example usage, see [the `terraform_remote_state` data source](https://opentofu.org/docs/v1.10/language/state/remote-state-data/) . While remote state can be a convenient, built-in mechanism for sharing data between configurations, you may prefer to use more general stores to pass settings both to other configurations and to other consumers. For example, if your environment has [HashiCorp Consul](https://www.consul.io/) then you can have one OpenTofu configuration that writes to Consul using [`consul_key_prefix`](https://registry.terraform.io/providers/hashicorp/consul/latest/docs/resources/key_prefix) and then another that consumes those values using [the `consul_keys` data source](https://registry.terraform.io/providers/hashicorp/consul/latest/docs/data-sources/keys) . Locking and Teamwork[​](https://opentofu.org/docs/v1.10/language/state/remote/#locking-and-teamwork "Direct link to Locking and Teamwork") ------------------------------------------------------------------------------------------------------------------------------------------- For fully-featured remote backends, OpenTofu can also use [state locking](https://opentofu.org/docs/v1.10/language/state/locking/) to prevent concurrent runs of OpenTofu against the same state. [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software) is a commercial offering that supports an even stronger locking concept that can also detect attempts to create a new plan when an existing plan is already awaiting approval, by queuing OpenTofu operations in a central location. This allows teams to more easily coordinate and communicate about changes to infrastructure. * [Delegation and Teamwork](https://opentofu.org/docs/v1.10/language/state/remote/#delegation-and-teamwork) * [Locking and Teamwork](https://opentofu.org/docs/v1.10/language/state/remote/#locking-and-teamwork) --- # Remote Service Discovery | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Remote Service Discovery ======================== OpenTofu implements much of its functionality in terms of remote services. While in many cases these are generic third-party services that are useful to many applications, some of these services are tailored specifically to OpenTofu's needs. We call these _OpenTofu-native services_, and OpenTofu interacts with them via the remote service discovery protocol described below. User-facing Hostname[​](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/#user-facing-hostname "Direct link to User-facing Hostname") -------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu-native services are provided, from a user's perspective, at a user-facing "friendly hostname" which serves as the key for configuration and for any authentication credentials required. The discovery protocol's purpose is to map from a user-provided hostname to the base URL of a particular service. Each host can provide different combinations of services -- or no services at all! -- and so the discovery protocol has a secondary purpose of allowing OpenTofu to identify _which_ services are valid for a given hostname. For example, module source strings can include a module registry hostname as their first segment, like `example.com/namespace/name/provider`, and OpenTofu uses service discovery to determine whether `example.com` _has_ a module registry, and if so where its API is available. A user-facing hostname is a fully-specified [internationalized domain name](https://en.wikipedia.org/wiki/Internationalized_domain_name) expressed in its Unicode form (the corresponding "punycode" form is not allowed) which must be resolvable in DNS to an address that has an HTTPS server running on port 443. User-facing hostnames are normalized for internal comparison using the standard Unicode [Nameprep](https://en.wikipedia.org/wiki/Nameprep) algorithm, which includes converting all letters to lowercase, normalizing combining diacritics to precomposed form where possible, and various other normalization steps. Discovery Process[​](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/#discovery-process "Direct link to Discovery Process") ----------------------------------------------------------------------------------------------------------------------------------------------- Given a hostname, discovery begins by forming an initial discovery URL using that hostname with the `https:` scheme and the fixed path `/.well-known/terraform.json`. For example, given the hostname `example.com` the initial discovery URL would be `https://example.com/.well-known/terraform.json`. OpenTofu then sends a `GET` request to this discovery URL and expects a JSON response. If the response does not have status 200, does not have a media type of `application/json` or, if the body cannot be parsed as a JSON object, then discovery fails and OpenTofu considers the host to not support _any_ OpenTofu-native services. If the response is an HTTP redirect then OpenTofu repeats this step with the new location as its discovery URL. OpenTofu is guaranteed to follow at least one redirect, but nested redirects are not guaranteed nor recommended. If the response is a valid JSON object then its keys are OpenTofu native service identifiers, consisting of a service type name and a version string separated by a period. For example, the service identifier for version 1 of the module registry protocol is `modules.v1`. The value of each object element is the base URL for the service in question. This URL may be either absolute or relative, and if relative it is resolved against the final discovery URL (_after_ following redirects). The following is an example discovery document declaring support for version 1 of the module registry protocol: Code Block { "modules.v1": "https://modules.example.com/v1/"} Supported Services[​](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/#supported-services "Direct link to Supported Services") -------------------------------------------------------------------------------------------------------------------------------------------------- At present, the following service identifiers are in use: * `login.v1`: [login protocol version 1](https://opentofu.org/docs/v1.11/cli/commands/login/) * `modules.v1`: [module registry API version 1](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/) * `providers.v1`: [provider registry API version 1](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/) Authentication[​](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/#authentication "Direct link to Authentication") -------------------------------------------------------------------------------------------------------------------------------------- If credentials for the given hostname are available in [the CLI config](https://opentofu.org/docs/v1.11/cli/config/config-file/#Credentials) through a `credentials_helper` or a host-specific environment variable, then they will be included in the request for the discovery document. The credentials may also be provided to endpoints declared in the discovery document, depending on the requirements of the service in question. Non-standard Ports in User-facing Hostnames[​](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/#non-standard-ports-in-user-facing-hostnames "Direct link to Non-standard Ports in User-facing Hostnames") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- It is strongly recommended to provide the discovery document for a hostname on the standard HTTPS port 443. However, in development environments this is not always possible or convenient, so OpenTofu allows a hostname to end with a port specification consisting of a colon followed by one or more decimal digits. When a custom port number is present, the service on that port is expected to implement HTTPS and respond to the same fixed discovery path. For day-to-day use it is strongly recommended _not_ to rely on this mechanism and to instead provide the discovery document on the standard port, since this allows use of the most user-friendly hostname form. * [User-facing Hostname](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/#user-facing-hostname) * [Discovery Process](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/#discovery-process) * [Supported Services](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/#supported-services) * [Authentication](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/#authentication) * [Non-standard Ports in User-facing Hostnames](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/#non-standard-ports-in-user-facing-hostnames) --- # Credentials Helpers | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Credentials Helpers =================== For OpenTofu-specific features that interact with remote network services, such as module registries, OpenTofu by default looks for API credentials to use in these calls in [the CLI configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/) . Credentials helpers offer an alternative approach that allows you to customize how OpenTofu obtains credentials using an external program, which can then directly access an existing secrets management system in your organization. This page is about how to write and install a credentials helper. To learn how to configure a credentials helper that was already installed, see [the CLI config Credentials Helpers section](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials-helpers) . How OpenTofu finds Credentials Helpers[​](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#how-opentofu-finds-credentials-helpers "Direct link to How OpenTofu finds Credentials Helpers") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A credentials helper is a normal executable program that is installed in a particular location and whose name follows a specific naming convention. A credentials helper called "credstore", for example, would be implemented as an executable program named `terraform-credentials-credstore` (with an `.exe` extension on Windows only), and installed in one of the [default plugin search locations](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation) . How OpenTofu runs Credentials Helpers[​](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#how-opentofu-runs-credentials-helpers "Direct link to How OpenTofu runs Credentials Helpers") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Once OpenTofu has located the configured credentials helper, it will execute it once for each credentials request that cannot be satisfied by a `credentials` block in the CLI configuration. For the following examples, we'll assume a "credstore" credentials helper configured as follows: Code Block credentials_helper "credstore" { args = ["--host=credstore.example.com"]} OpenTofu runs the helper program with each of the arguments given in `args`, followed by an _verb_ and then the hostname that the verb will apply to. The current set of verbs are: * `get`: retrieve the credentials for the given hostname * `store`: store new credentials for the given hostname * `forget`: delete any stored credentials for the given hostname To represent credentials, the credentials helper protocol uses a JSON object whose contents correspond with the contents of [`credentials` blocks in the CLI configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials) . To represent an API token, the object contains a property called "token" whose value is the token string: Code Block { "token": "example-token-value"} The following sections describe the specific expected behaviors for each of the three verbs. `get`: retrieve the credentials for the given hostname[​](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#get-retrieve-the-credentials-for-the-given-hostname "Direct link to get-retrieve-the-credentials-for-the-given-hostname") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To retrieve credentials for `app.example.io`, OpenTofu would run the "credstore" helper as follows: Code Block terraform-credentials-credstore --host=credstore.example.com get app.example.io If the credentials helper is able to provide credentials for the given host then it must print a JSON credentials object to its stdout stream and then exit with status code zero to indicate success. If the credentials helper definitively has no credentials for the given host, then it must print an empty JSON object to stdout and exit with status zero. If the credentials helper is unable to provide the requested credentials for any other reason, it must print an end-user-oriented plain text error message to its stderr stream and then exit with a _non-zero_ status code. `store`: store new credentials for the given hostname[​](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#store-store-new-credentials-for-the-given-hostname "Direct link to store-store-new-credentials-for-the-given-hostname") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ To store new credentials for `app.example.io`, OpenTofu would run the "credstore" helper as follows: Code Block terraform-credentials-credstore --host=credstore.example.com store app.example.io OpenTofu then writes a JSON credentials object to the helper program's stdin stream. If the helper is able to store the given credentials then it must do so and then exit with status code zero and no output on stdout or stderr to indicate success. If it is unable to store the given credentials for any reason, it _must_ still fully read its stdin until EOF and then print an end-user-oriented plain text error message to its stderr stream before exiting with a non-zero status code. The new credentials must fully replace any existing credentials stored for the given hostname. `forget`: delete any stored credentials for the given hostname[​](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#forget-delete-any-stored-credentials-for-the-given-hostname "Direct link to forget-delete-any-stored-credentials-for-the-given-hostname") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To forget any existing credentials for `app.example.io`, OpenTofu would run the "credstore" helper as follows: Code Block terraform-credentials-credstore --host=credstore.example.com forget app.example.io No JSON credentials objects are used for the `forget` verb. If the helper program is able to delete its stored credentials for the given hostname or if there are no such credentials stored already then it must exist with status code zero and produce no output on stdout or stderr. If it is unable to forget the stored credentials for any reason, particularly if the helper cannot be sure that the credentials are no longer available for retrieval, the helper program must print an end-user-oriented plain text error message to its stderr stream and then exit with a non-zero status code. Handling Other Commands[​](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#handling-other-commands "Direct link to Handling Other Commands") ------------------------------------------------------------------------------------------------------------------------------------------------------------ The credentials helper protocol may be extended with additional verbs in future, so for forward-compatibility a credentials helper must react to any unsupported verb by printing an end-user-oriented plain text error message to its stderr stream and then exiting with a non-zero status code. Handling Unsupported Credentials Object Properties[​](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#handling-unsupported-credentials-object-properties "Direct link to Handling Unsupported Credentials Object Properties") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu defines only the `token` property within JSON credentials objects. If a credentials helper is asked to store an object that has any properties other than `token` and if it is not able to faithfully retain them then it must behave as if the object is unstorable, returning an error. It must _not_ store the `token` value in isolation and silently drop other properties, as that might change the meaning of the credentials object. If technically possible within the constraints of the target system, a credentials helper should prefer to store the whole JSON object as-is for later retrieval. For systems that are more constrained, it's acceptable to store only the `token` string so long as the program rejects objects containing other properties as described above. Installing a Credentials Helper[​](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#installing-a-credentials-helper "Direct link to Installing a Credentials Helper") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ OpenTofu does not have any automatic installation mechanism for credentials helpers. Instead, the user must extract the helper program executable into one of the [default plugin search locations](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation) . If you are packaging a credentials helper for distribution, place it in an named with the expected naming scheme (`terraform-credentials-example`) and, if the containing archive format supports it and it's meaningful for the target operating system, mark the file as executable to increase the chances that it will work immediately after extraction. OpenTofu does _not_ honor the `-plugin-dir` argument to `tofu init` when searching for credentials helpers, because credentials are also used by other commands that can be run prior to `tofu init`. Only the default search locations are supported. * [How OpenTofu finds Credentials Helpers](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#how-opentofu-finds-credentials-helpers) * [How OpenTofu runs Credentials Helpers](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#how-opentofu-runs-credentials-helpers) * [`get`: retrieve the credentials for the given hostname](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#get-retrieve-the-credentials-for-the-given-hostname) * [`store`: store new credentials for the given hostname](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#store-store-new-credentials-for-the-given-hostname) * [`forget`: delete any stored credentials for the given hostname](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#forget-delete-any-stored-credentials-for-the-given-hostname) * [Handling Other Commands](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#handling-other-commands) * [Handling Unsupported Credentials Object Properties](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#handling-unsupported-credentials-object-properties) * [Installing a Credentials Helper](https://opentofu.org/docs/v1.11/internals/credentials-helpers/#installing-a-credentials-helper) --- # Module Registry Protocol | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Module Registry Protocol ======================== The module registry protocol is what OpenTofu CLI uses to discover metadata about modules available for installation and to locate the distribution package for a selected module. The primary implementation of this protocol is the public [OpenTofu Registry](https://registry.opentofu.org/) at `registry.opentofu.org`. By writing and deploying your own implementation of this protocol, you can create a separate registry to distribute your own modules, as an alternative to publishing them on the public OpenTofu Registry. Module Addresses[​](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#module-addresses "Direct link to Module Addresses") -------------------------------------------------------------------------------------------------------------------------------------------- Each OpenTofu module has an associated address. A module address has the syntax `hostname/namespace/name/system`, where: * `hostname` is the hostname of the module registry that serves this module. * `namespace` is the name of a namespace, unique on a particular hostname, that can contain one or more modules that are somehow related. On the public OpenTofu Registry the "namespace" represents the organization that is packaging and distributing the module. * `name` is the module name, which generally names the abstraction that the module is intending to create. * `system` is the name of a remote system that the module is primarily written to target. For multi-cloud abstractions, there can be multiple modules with addresses that differ only in "system" to reflect provider-specific implementations of the abstraction, like `registry.opentofu.org/hashicorp/consul/aws` vs. `registry.opentofu.org/hashicorp/consul/azurerm`. The system name commonly matches the type portion of the address of an official provider, like `aws` or `azurerm` in the above examples, but that is not required and so you can use whichever system keywords make sense for the organization of your particular registry. The `hostname/` portion of a module address (including its slash delimiter) is optional, and if omitted defaults to `registry.opentofu.org/`. For example: * `hashicorp/consul/aws` is a shorthand for `registry.opentofu.org/hashicorp/consul/aws`, which is a module on the public registry for deploying Consul clusters in Amazon Web Services. * `example.com/awesomecorp/consul/happycloud` is a hypothetical module published on a third-party registry. If you intend to share a module you've developed for use by all OpenTofu users, please consider publishing it into the public [OpenTofu Registry](https://registry.opentofu.org/) to make your module more discoverable. You only need to implement this module registry protocol if you wish to publish modules whose addresses include a different hostname that is under your control. Module Versions[​](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#module-versions "Direct link to Module Versions") ----------------------------------------------------------------------------------------------------------------------------------------- Each distinct module address has associated with it a set of versions, each of which has an associated version number. OpenTofu assumes version numbers follow the [Semantic Versioning 2.0](https://semver.org/) conventions, with the user-facing behavior of the module serving as the "public API". Each `module` block may select a distinct version of a module, even if multiple blocks have the same source address. Service Discovery[​](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#service-discovery "Direct link to Service Discovery") ----------------------------------------------------------------------------------------------------------------------------------------------- The module registry protocol begins with OpenTofu CLI using [OpenTofu's remote service discovery protocol](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/) , with the hostname in the module address acting as the "User-facing Hostname". The service identifier for the module registry protocol is `modules.v1`. Its associated string value is the base URL for the relative URLs defined in the sections that follow. For example, the service discovery document for a host that _only_ implements the module registry protocol might contain the following: Code Block { "modules.v1": "/tofu/modules/v1/"} If the given URL is a relative URL then OpenTofu will interpret it as relative to the discovery document itself. The specific module registry protocol endpoints are defined as URLs relative to the given base URL, and so the specified base URL should generally end with a slash to ensure that those relative paths will be resolved as expected. The following sections describe the various operations that a module registry must implement to be compatible with OpenTofu CLI's module installer. The indicated URLs are all relative to the URL resulting from service discovery, as described above. We use a hypothetical URL for a provider registry, assuming that the caller already performed service discovery on a hypothetical `registry.example.io` to learn the base URL. The URLs are shown with the convention that a path portion with a colon `:` prefix is a placeholder for a dynamically-selected value, while all other path portions are literal. For example, in `:namespace/:type/versions`, the first two path portions are placeholders while the third is literally the string "versions". List Available Versions for a Specific Module[​](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#list-available-versions-for-a-specific-module "Direct link to List Available Versions for a Specific Module") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This is the primary endpoint for resolving module sources, returning the available versions for a given fully-qualified module. | Method | Path | Produces | | --- | --- | --- | | `GET` | `:namespace/:name/:system/versions` | `application/json` | ### Parameters[​](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#parameters "Direct link to Parameters") * `namespace` `(string: )` - The user or organization the module is owned by. This is required and is specified as part of the URL path. * `name` `(string: )` - The name of the module. This is required and is specified as part of the URL path. * `system` `(string: )` - The name of the target system. This is required and is specified as part of the URL path. ### Sample Request[​](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#sample-request "Direct link to Sample Request") Code Block $ curl 'https://registry.opentofu.org/v1/modules/hashicorp/consul/aws/versions' ### Sample Response[​](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#sample-response "Direct link to Sample Response") The `modules` array in the response always includes the requested module as the first element. OpenTofu does not use the other elements of this list. However, third-party implementations should always use a single-element list for forward compatibility. Each returned module has an array of available versions, which OpenTofu matches against any version constraints given in configuration. Code Block { "modules": [ { "versions": [ {"version": "1.0.0"}, {"version": "1.1.0"}, {"version": "2.0.0"} ] } ]} Return `404 Not Found` to indicate that no module is available with the requested namespace, name, and target system. Download Source Code for a Specific Module Version[​](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#download-source-code-for-a-specific-module-version "Direct link to Download Source Code for a Specific Module Version") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This endpoint downloads the specified version of a module for a single target system. | Method | Path | Produces | | --- | --- | --- | | `GET` | `:namespace/:name/:system/:version/download` | `application/json` | ### Parameters[​](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#parameters-1 "Direct link to Parameters") * `namespace` `(string: )` - The user the module is owned by. This is required and is specified as part of the URL path. * `name` `(string: )` - The name of the module. This is required and is specified as part of the URL path. * `system` `(string: )` - The name of the target system. This is required and is specified as part of the URL path. * `version` `(string: )` - The version of the module. This is required and is specified as part of the URL path. ### Sample Request[​](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#sample-request-1 "Direct link to Sample Request") Code Block $ curl -i 'https://registry.opentofu.org/v1/modules/foo/bar/baz/0.0.1/download' ### Sample Response[​](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#sample-response-1 "Direct link to Sample Response") A successful response contains the location from which the module version's source can be downloaded. It is expected to be found in the JSON encoded body as the value for the key `location`: Code Block HTTP/2 200Content-Length: 81{"location": "git::https://github.com/foo/terraform-baz-bar?ref=v0.0.1"} In the absence of a response body, OpenTofu will use the `X-Terraform-Get` header as the module location: Code Block HTTP/2 204 No ContentContent-Length: 0X-Terraform-Get: git::https://github.com/foo/terraform-baz-bar?ref=v0.0.1 Warning OpenTofu will prioritize reading the response body content if both, the body and the `X-Terraform-Get` header, are received from the registry server. The module location value accepts the same values as the `source` argument in a `module` block in OpenTofu configuration, as described in [Module Sources](https://opentofu.org/docs/v1.11/language/modules/sources/) , except that it may not recursively refer to another module registry address. The value of the module location may instead be a relative URL, indicated by beginning with `/`, `./` or `../`, in which case it is resolved relative to the full URL of the download endpoint to produce [an HTTP URL module source](https://opentofu.org/docs/v1.11/language/modules/sources/#http-urls) . * [Module Addresses](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#module-addresses) * [Module Versions](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#module-versions) * [Service Discovery](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#service-discovery) * [List Available Versions for a Specific Module](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#list-available-versions-for-a-specific-module) * [Parameters](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#parameters) * [Sample Request](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#sample-request) * [Sample Response](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#sample-response) * [Download Source Code for a Specific Module Version](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#download-source-code-for-a-specific-module-version) * [Parameters](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#parameters-1) * [Sample Request](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#sample-request-1) * [Sample Response](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/#sample-response-1) --- # OpenTofu vs. CloudFormation, Heat, etc. | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/vs/cloudformation/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) OpenTofu vs. CloudFormation, Heat, etc. ======================================= Tools like CloudFormation, Heat, etc. allow the details of an infrastructure to be codified into a configuration file. The configuration files allow the infrastructure to be elastically created, modified and destroyed. OpenTofu is inspired by the problems they solve. OpenTofu similarly uses configuration files to detail the infrastructure setup, but it goes further by being both cloud-agnostic and enabling multiple providers and services to be combined and composed. For example, OpenTofu can be used to orchestrate an AWS and OpenStack cluster simultaneously, while enabling 3rd-party providers like Cloudflare and DNSimple to be integrated to provide CDN and DNS services. This enables OpenTofu to represent and manage the entire infrastructure with its supporting services, instead of only the subset that exists within a single provider. It provides a single unified syntax, instead of requiring operators to use independent and non-interoperable tools for each platform and service. OpenTofu also separates the planning phase from the execution phase, by using the concept of an execution plan. By running `tofu plan`, the current state is refreshed and the configuration is consulted to generate an action plan. The plan includes all actions to be taken: which resources will be created, destroyed or modified. It can be inspected by operators to ensure it is exactly what is expected. Using `tofu graph`, the plan can be visualized to show dependent ordering. Once the plan is captured, the execution phase can be limited to only the actions in the plan. Other tools combine the planning and execution phases, meaning operators are forced to mentally reason about the effects of a change, which quickly becomes intractable in large infrastructures. OpenTofu lets operators apply changes with confidence, as they know exactly what will happen beforehand. --- # Refactoring | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Refactoring =========== Module resources[​](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#module-resources "Direct link to Module resources") ---------------------------------------------------------------------------------------------------------------------------------------------- In shared modules and long-lived configurations, you may eventually outgrow your initial module structure and resource names. For example, you might decide that what was previously one child module makes more sense as two separate modules and move a subset of the existing resources to the new one. OpenTofu compares previous state with new configuration, correlating by each module or resource's unique address. Therefore _by default_ OpenTofu understands moving or renaming an object as an intent to destroy the object at the old address and to create a new object at the new address. When you add `moved` blocks in your configuration to record where you've historically moved or renamed an object, OpenTofu treats an existing object at the old address as if it now belongs to the new address. ### `moved` Block Syntax[​](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#moved-block-syntax "Direct link to moved-block-syntax") A `moved` block expects no labels and contains only `from` and `to` arguments: Code Block moved { from = aws_instance.a to = aws_instance.b} The example above records that the resource currently known as `aws_instance.b` was known as `aws_instance.a` in a previous version of this module. Before creating a new plan for `aws_instance.b`, OpenTofu first checks whether there is an existing object for `aws_instance.a` recorded in the state. If there is an existing object, OpenTofu renames that object to `aws_instance.b` and then proceeds with creating a plan. The resulting plan is as if the object had originally been created at `aws_instance.b`, avoiding any need to destroy it during apply. The `from` and `to` addresses both use a special addressing syntax that allows selecting modules, resources, and resources inside child modules. Below, we describe several refactoring use-cases and the appropriate addressing syntax for each situation. * [Renaming a Resource](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#renaming-a-resource) * [Changing a Resource Type](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#changing-a-resource-type) * [Enabling `count` or `for_each` For a Resource](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#enabling-count-or-for_each-for-a-resource) * [Renaming a Module Call](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#renaming-a-module-call) * [Enabling `count` or `for_each` For a Module Call](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#enabling-count-or-for_each-for-a-module-call) * [Splitting One Module into Multiple](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#splitting-one-module-into-multiple) * [Removing `moved` blocks](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#removing-moved-blocks) ### Renaming a Resource[​](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#renaming-a-resource "Direct link to Renaming a Resource") Consider this example module with a resource configuration: Code Block resource "aws_instance" "a" { count = 2 # (resource-type-specific configuration)} Applying this configuration for the first time would cause OpenTofu to create `aws_instance.a[0]` and `aws_instance.a[1]`. If you later choose a different name for this resource, then you can change the name label in the `resource` block and record the old name inside a `moved` block: Code Block resource "aws_instance" "b" { count = 2 # (resource-type-specific configuration)}moved { from = aws_instance.a to = aws_instance.b} When creating the next plan for each configuration using this module, OpenTofu treats any existing objects belonging to `aws_instance.a` as if they had been created for `aws_instance.b`: `aws_instance.a[0]` will be treated as `aws_instance.b[0]`, and `aws_instance.a[1]` as `aws_instance.b[1]`. New instances of the module, which _never_ had an `aws_instance.a`, will ignore the `moved` block and propose to create `aws_instance.b[0]` and `aws_instance.b[1]` as normal. Both of the addresses in this example referred to a resource as a whole, and so OpenTofu recognizes the move for all instances of the resource. That is, it covers both `aws_instance.a[0]` and `aws_instance.a[1]` without the need to identify each one separately. ### Changing a Resource Type[​](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#changing-a-resource-type "Direct link to Changing a Resource Type") Each resource type has a separate schema, so objects of different types are not generally compatible. However, some providers will let you change an object from one resource type to another. It is also possible to change one provider's resource to another provider's resource, as long as the new provider supports migration from the old resource. Refer to the provider documentation for more information about resource compatibility. You can use `moved` to change the name (and sometimes type) of a resource, but you _cannot_ use `moved` to change a managed resource (a `resource` block) into a data resource (a `data` block). ### Enabling `count` or `for_each` For a Resource[​](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#enabling-count-or-for_each-for-a-resource "Direct link to enabling-count-or-for_each-for-a-resource") Consider this example module containing a single-instance resource: Code Block resource "aws_instance" "a" { # (resource-type-specific configuration)} Applying this configuration would lead to OpenTofu creating an object bound to the address `aws_instance.a`. Later, you use [`for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) with this resource to systematically declare multiple instances. To preserve an object that was previously associated with `aws_instance.a` alone, you must add a `moved` block to specify which instance key the object will take in the new configuration: Code Block locals { instances = tomap({ big = { instance_type = "m3.large" } small = { instance_type = "t2.medium" } })}resource "aws_instance" "a" { for_each = local.instances instance_type = each.value.instance_type # (other resource-type-specific configuration)}moved { from = aws_instance.a to = aws_instance.a["small"]} The above will keep OpenTofu from planning to destroy any existing object at `aws_instance.a`, treating that object instead as if it were originally created as `aws_instance.a["small"]`. When at least one of the two addresses includes an instance key, like `["small"]` in the above example, OpenTofu understands both addresses as referring to specific _instances_ of a resource rather than the resource as a whole. That means you can use `moved` to switch between keys and to add and remove keys as you switch between `count`, `for_each`, or neither. The following are some other examples of valid `moved` blocks that record changes to resource instance keys in a similar way: Code Block # Both old and new configuration used "for_each", but the# "small" element was renamed to "tiny".moved { from = aws_instance.b["small"] to = aws_instance.b["tiny"]}# The old configuration used "count" and the new configuration# uses "for_each", with the following mappings from# index to key:moved { from = aws_instance.c[0] to = aws_instance.c["small"]}moved { from = aws_instance.c[1] to = aws_instance.c["tiny"]}# The old configuration used "count", and the new configuration# uses neither "count" nor "for_each", and you want to keep# only the object at index 2.moved { from = aws_instance.d[2] to = aws_instance.d} Note When you add `count` to an existing resource that didn't use it, OpenTofu automatically proposes to move the original object to instance zero, unless you write an `moved` block explicitly mentioning that resource. However, we recommend still writing out the corresponding `moved` block explicitly, to make the change clearer to future readers of the module. ### Renaming a Module Call[​](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#renaming-a-module-call "Direct link to Renaming a Module Call") You can rename a call to a module in a similar way as renaming a resource. Consider the following original module version: Code Block module "a" { source = "../modules/example" # (module arguments)} When applying this configuration, OpenTofu would prefix the addresses for any resources declared in this module with the module path `module.a`. For example, a resource `aws_instance.example` would have the full address `module.a.aws_instance.example`. If you later choose a better name for this module call, then you can change the name label in the `module` block and record the old name inside a `moved` block: Code Block module "b" { source = "../modules/example" # (module arguments)}moved { from = module.a to = module.b} When creating the next plan for each configuration using this module, OpenTofu will treat any existing object addresses beginning with `module.a` as if they had instead been created in `module.b`. `module.a.aws_instance.example` would be treated as `module.b.aws_instance.example`. Both of the addresses in this example referred to a module call as a whole, and so OpenTofu recognizes the move for all instances of the call. If this module call used `count` or `for_each` then it would apply to all of the instances, without the need to specify each one separately. ### Enabling `count` or `for_each` For a Module Call[​](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#enabling-count-or-for_each-for-a-module-call "Direct link to enabling-count-or-for_each-for-a-module-call") Consider this example of a single-instance module: Code Block module "a" { source = "../modules/example" # (module arguments)} Applying this configuration would cause OpenTofu to create objects whose addresses begin with `module.a`. In later module versions, you may need to use [`count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) with this resource to systematically declare multiple instances. To preserve an object that was previously associated with `aws_instance.a` alone, you can add a `moved` block to specify which instance key that object will take in the new configuration: Code Block module "a" { source = "../modules/example" count = 3 # (module arguments)}moved { from = module.a to = module.a[2]} The configuration above directs OpenTofu to treat all objects in `module.a` as if they were originally created in `module.a[2]`. As a result, OpenTofu plans to create new objects only for `module.a[0]` and `module.a[1]`. When at least one of the two addresses includes an instance key, like `[2]` in the above example, OpenTofu will understand both addresses as referring to specific _instances_ of a module call rather than the module call as a whole. That means you can use `moved` to switch between keys and to add and remove keys as you switch between `count`, `for_each`, or neither. For more examples of recording moves associated with instances, refer to the similar section [Enabling `count` and `for_each` For a Resource](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#enabling-count-or-for_each-for-a-resource) . Splitting One Module into Multiple ================================== As a module grows to support new requirements, it might eventually grow big enough to warrant splitting into two separate modules. Consider this example module: Code Block resource "aws_instance" "a" { # (other resource-type-specific configuration)}resource "aws_instance" "b" { # (other resource-type-specific configuration)}resource "aws_instance" "c" { # (other resource-type-specific configuration)} You can split this into two modules as follows: * `aws_instance.a` now belongs to module "x". * `aws_instance.b` also belongs to module "x". * `aws_instance.c` belongs module "y". To achieve this refactoring without replacing existing objects bound to the old resource addresses, you must: 1. Write module "x", copying over the two resources it should contain. 2. Write module "y", copying over the one resource it should contain. 3. Edit the original module to no longer include any of these resources, and instead to contain only shim configuration to migrate existing users. The new modules "x" and "y" should contain only `resource` blocks: Code Block # module "x"resource "aws_instance" "a" { # (other resource-type-specific configuration)}resource "aws_instance" "b" { # (other resource-type-specific configuration)} Code Block # module "y"resource "aws_instance" "c" { # (other resource-type-specific configuration)} The original module, now only a shim for backward-compatibility, calls the two new modules and indicates that the resources moved into them: Code Block module "x" { source = "../modules/x" # ...}module "y" { source = "../modules/y" # ...}moved { from = aws_instance.a to = module.x.aws_instance.a}moved { from = aws_instance.b to = module.x.aws_instance.b}moved { from = aws_instance.c to = module.y.aws_instance.c} When an existing user of the original module upgrades to the new "shim" version, OpenTofu notices these three `moved` blocks and behaves as if the objects associated with the three old resource addresses were originally created inside the two new modules. New users of this family of modules may use either the combined shim module _or_ the two new modules separately. You may wish to communicate to your existing users that the old module is now deprecated and so they should use the two separate modules for any new needs. The multi-module refactoring situation is unusual in that it violates the typical rule that a parent module sees its child module as a "closed box", unaware of exactly which resources are declared inside it. This compromise assumes that all three of these modules are maintained by the same people and distributed together in a single [module package](https://opentofu.org/docs/v1.10/language/modules/sources/#modules-in-package-sub-directories) . OpenTofu resolves module references in `moved` blocks relative to the module instance they are defined in. For example, if the original module above were already a child module named `module.original`, the reference to `module.x.aws_instance.a` would resolve as `module.original.module.x.aws_instance.a`. A module may only make `moved` statements about its own objects and objects of its child modules. If you need to refer to resources within a module that was called using `count` or `for_each` meta-arguments, you must specify a specific instance key to use in order to match with the new location of the resource configuration: Code Block moved { from = aws_instance.example to = module.new[2].aws_instance.example} ### Removing `moved` Blocks[​](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#removing-moved-blocks "Direct link to removing-moved-blocks") Over time, a long-lasting module may accumulate many `moved` blocks. Removing a `moved` block is a generally breaking change because any configurations that refer to the old address will plan to delete that existing object instead of move it. We strongly recommend that you retain all historical `moved` blocks from earlier versions of your modules to preserve the upgrade path for users of any previous version. If you do decide to remove `moved` blocks, proceed with caution. It can be safe to remove `moved` blocks when you are maintaining private modules within an organization and you are certain that all users have successfully run `tofu apply` with your new module version. If you need to rename or move the same object twice, we recommend documenting the full history using _chained_ `moved` blocks, where the new block refers to the existing block: Code Block moved { from = aws_instance.a to = aws_instance.b}moved { from = aws_instance.b to = aws_instance.c} Recording a sequence of moves in this way allows for successful upgrades for both configurations with objects at `aws_instance.a` _and_ configurations with objects at `aws_instance.b`. In both cases, OpenTofu treats the existing object as if it had been originally created as `aws_instance.c`. Module variables and outputs[​](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#module-variables-and-outputs "Direct link to Module variables and outputs") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Warning This feature is considered experimental and the final UX may change in the future. Refactoring module variables and outputs requires additional changes from module callers. To properly communicate variables and outputs deprecation, module authors can prepare their configuration to warn callers about future removal. OpenTofu supports `deprecated` attributes for variable and output blocks with a suggestion from module author on how to properly migrate away on deprecation. Module callers receive a warning if their configuration is affected. Note Due to the internal logic of values evaluation, deprecation warnings for module outputs will not be raised for commands like `tofu validate`. OpenTofu produces all the expected deprecation warnings on `tofu plan` and `tofu apply` commands. Refer to `deprecated` attribute of [variables](https://opentofu.org/docs/v1.10/language/values/variables/#marking-variable-as-deprecated) and [module outputs](https://opentofu.org/docs/v1.10/language/values/outputs/#deprecated--marking-output-as-deprecated) for more information. * [Module resources](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#module-resources) * [`moved` Block Syntax](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#moved-block-syntax) * [Renaming a Resource](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#renaming-a-resource) * [Changing a Resource Type](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#changing-a-resource-type) * [Enabling `count` or `for_each` For a Resource](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#enabling-count-or-for_each-for-a-resource) * [Renaming a Module Call](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#renaming-a-module-call) * [Enabling `count` or `for_each` For a Module Call](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#enabling-count-or-for_each-for-a-module-call) * [Removing `moved` Blocks](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#removing-moved-blocks) * [Module variables and outputs](https://opentofu.org/docs/v1.10/language/modules/develop/refactoring/#module-variables-and-outputs) --- # Resource Blocks | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/resources/syntax/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Resource Blocks =============== _Resources_ are the most important element in the OpenTofu language. Each resource block describes one or more infrastructure objects, such as virtual networks, compute instances, or higher-level components such as DNS records. Resource Syntax[​](https://opentofu.org/docs/v1.10/language/resources/syntax/#resource-syntax "Direct link to Resource Syntax") -------------------------------------------------------------------------------------------------------------------------------- Resource declarations can include a number of advanced features, but only a small subset are required for initial use. More advanced syntax features, such as single resource declarations that produce multiple similar remote objects, are described later in this page. Code Block resource "aws_instance" "web" { ami = "ami-a1b2c3d4" instance_type = "t2.micro"} A `resource` block declares a resource of a given type ("aws\_instance") with a given local name ("web"). The name is used to refer to this resource from elsewhere in the same module, but has no significance outside that module's scope. The resource type and name together serve as an identifier for a given resource and so must be unique within a module. Within the block body (between `{` and `}`) are the configuration arguments for the resource itself. Most arguments in this section depend on the resource type, and indeed in this example both `ami` and `instance_type` are arguments defined specifically for [the `aws_instance` resource type](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) . Note Resource names must start with a letter or underscore, and may contain only letters, digits, underscores, and dashes. Resource Types[​](https://opentofu.org/docs/v1.10/language/resources/syntax/#resource-types "Direct link to Resource Types") ----------------------------------------------------------------------------------------------------------------------------- Each resource is associated with a single _resource type_, which determines the kind of infrastructure object it manages and what arguments and other attributes the resource supports. ### Providers[​](https://opentofu.org/docs/v1.10/language/resources/syntax/#providers "Direct link to Providers") Each resource type is implemented by a [provider](https://opentofu.org/docs/v1.10/language/providers/requirements/) , which is a plugin for OpenTofu that offers a collection of resource types. A provider usually provides resources to manage a single cloud or on-premises infrastructure platform. Providers are distributed separately from OpenTofu itself, but OpenTofu can automatically install most providers when initializing a working directory. In order to manage resources, a module must specify which providers it requires. Additionally, most providers need some configuration in order to access their remote APIs, and the root module must provide that configuration. For more information, see: * [Provider Requirements](https://opentofu.org/docs/v1.10/language/providers/requirements/) , for declaring which providers a module uses. * [Provider Configuration](https://opentofu.org/docs/v1.10/language/providers/configuration/) , for configuring provider settings. OpenTofu usually automatically determines which provider to use based on a resource type's name. (By convention, resource type names start with their provider's preferred local name.) When using multiple configurations of a provider (or non-preferred local provider names), you must use the `provider` meta-argument to manually choose an alternate provider configuration. See [the `provider` meta-argument](https://opentofu.org/docs/v1.10/language/meta-arguments/resource-provider/) for more details. ### Resource Arguments[​](https://opentofu.org/docs/v1.10/language/resources/syntax/#resource-arguments "Direct link to Resource Arguments") Most of the arguments within the body of a `resource` block are specific to the selected resource type. The resource type's documentation lists which arguments are available and how their values should be formatted. The values for resource arguments can make full use of [expressions](https://opentofu.org/docs/v1.10/language/expressions/) and other dynamic OpenTofu language features. There are also some _meta-arguments_ that are defined by OpenTofu itself and apply across all resource types. (See [Meta-Arguments](https://opentofu.org/docs/v1.10/language/resources/syntax/#meta-arguments) below.) ### Documentation for Resource Types[​](https://opentofu.org/docs/v1.10/language/resources/syntax/#documentation-for-resource-types "Direct link to Documentation for Resource Types") Every provider has its own documentation, describing its resource types and their arguments. Most publicly available providers are distributed on the [Public Terraform Registry](https://registry.terraform.io/browse/providers) , which also hosts their documentation. When viewing a provider's page on the OpenTofu Registry, you can click the "Documentation" link in the header to browse its documentation. Provider documentation on the registry is versioned, and you can use the dropdown version menu in the header to switch which version's documentation you are viewing. To browse the publicly available providers and their documentation, see the [Public Terraform Registry](https://registry.terraform.io/browse/providers) . Note Provider documentation previously existed as part of OpenTofu's core documentation. Although some provider documentation might still be hosted here, the Public OpenTofu Registry is now the main home for all public provider docs. Resource Behavior[​](https://opentofu.org/docs/v1.10/language/resources/syntax/#resource-behavior "Direct link to Resource Behavior") -------------------------------------------------------------------------------------------------------------------------------------- For more information about how OpenTofu manages resources when applying a configuration, see [Resource Behavior](https://opentofu.org/docs/v1.10/language/resources/behavior/) . Removing Resources[​](https://opentofu.org/docs/v1.10/language/resources/syntax/#removing-resources "Direct link to Removing Resources") ----------------------------------------------------------------------------------------------------------------------------------------- If you remove a resource block from your configuration, OpenTofu will destroy it as a default behavior. However, there are instances when you want to remove a resource from your configuration without destroying the corresponding infrastructure object. In such cases, you can remove it from the [OpenTofu state](https://opentofu.org/docs/v1.10/language/state/) while allowing it to persist in the remote system. To achieve this, follow these steps: 1. Delete the resource from your configuration. 2. Add a removed block instead, specifying the resource address you want to "forget" in the `from` attribute. 3. Specify the `lifecycle.destroy = false` For example: Code Block removed { from = aws_instance.web lifecycle { destroy = false }} Note The address in the `from` attribute cannot include instance keys (for example, "aws\_instance.web\[0\]"). Note The `lifecycle.destroy` can be also `true`, case in which OpenTofu will behave just like the resource was deleted from the configuration. Though, we allow this since such a `removed` block can be used as historical hint about the previously existing resource. Warning The `lifecycle` block is not required, but it's highly recommended to be added. OpenTofu will also generate a warning if it finds any `removed` block without a `lifecycle` block defined inside. This is just to ensure that the user adding the `removed` block is indicating clearly what the block is meant to do. Upon executing `tofu plan`, OpenTofu will indicate that the resource is slated for removal from the state but will not be destroyed. The `removed` blocks do also support inner `provisioner` blocks. This is useful when the `resource` that is targeted to be removed was having `provisioner` blocks that the user wants to have executed before destroying the actual resource. Code Block removed { from = aws_s3_bucket.example lifecycle { destroy = true } provisioner "local-exec" { when = destroy command = "echo 'destroying bucket ${self.bucket}'" }} The `command` field do support references only the `self` object, `each.key` and `count.index`, which represents the information that OpenTofu is still having in the state about the targeted `resource`. The `provisioner` block will be executed only when the `removed` block is configured in a specific way: * `lifecycle.destroy = true` * `provisioner.when = destroy` In any other cases, the execution will be skipped. For more information about provisioners, you can refer to this [page](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/) . Meta-Arguments[​](https://opentofu.org/docs/v1.10/language/resources/syntax/#meta-arguments "Direct link to Meta-Arguments") ----------------------------------------------------------------------------------------------------------------------------- The OpenTofu language defines several meta-arguments, which can be used with any resource type to change the behavior of resources. The following meta-arguments are documented on separate pages: * [`depends_on`, for specifying hidden dependencies](https://opentofu.org/docs/v1.10/language/meta-arguments/depends_on/) * [`count`, for creating multiple resource instances according to a count](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) * [`for_each`, to create multiple instances according to a map, or set of strings](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) * [`provider`, for selecting a non-default provider configuration](https://opentofu.org/docs/v1.10/language/meta-arguments/resource-provider/) * [`lifecycle`, for lifecycle customizations](https://opentofu.org/docs/v1.10/language/meta-arguments/lifecycle/) * [`provisioner`, for taking extra actions after resource creation](https://opentofu.org/docs/v1.10/language/resources/provisioners/syntax/) Custom Condition Checks[​](https://opentofu.org/docs/v1.10/language/resources/syntax/#custom-condition-checks "Direct link to Custom Condition Checks") -------------------------------------------------------------------------------------------------------------------------------------------------------- You can use `precondition` and `postcondition` blocks to specify assumptions and guarantees about how the resource operates. The following example creates a precondition that checks whether the AMI is properly configured. Code Block resource "aws_instance" "example" { instance_type = "t2.micro" ami = "ami-abc123" lifecycle { # The AMI ID must refer to an AMI that contains an operating system # for the `x86_64` architecture. precondition { condition = data.aws_ami.example.architecture == "x86_64" error_message = "The selected AMI must be for the x86_64 architecture." } }} Custom conditions can help capture assumptions, helping future maintainers understand the configuration design and intent. They also return useful information about errors earlier and in context, helping consumers more easily diagnose issues in their configurations. Refer to [Custom Condition Checks](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#preconditions-and-postconditions) for more details. Operation Timeouts[​](https://opentofu.org/docs/v1.10/language/resources/syntax/#operation-timeouts "Direct link to Operation Timeouts") ----------------------------------------------------------------------------------------------------------------------------------------- Some resource types provide a special `timeouts` nested block argument that allows you to customize how long certain operations are allowed to take before being considered to have failed. For example, [`aws_db_instance`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance) allows configurable timeouts for `create`, `update` and `delete` operations. Timeouts are handled entirely by the resource type implementation in the provider, but resource types offering these features follow the convention of defining a child block called `timeouts` that has a nested argument named after each operation that has a configurable timeout value. Each of these arguments takes a string representation of a duration, such as `"60m"` for 60 minutes, `"10s"` for ten seconds, or `"2h"` for two hours. Code Block resource "aws_db_instance" "example" { # ... timeouts { create = "60m" delete = "2h" }} The set of configurable operations is chosen by each resource type. Most resource types do not support the `timeouts` block at all. Consult the documentation for each resource type to see which operations it offers for configuration, if any. * [Resource Syntax](https://opentofu.org/docs/v1.10/language/resources/syntax/#resource-syntax) * [Resource Types](https://opentofu.org/docs/v1.10/language/resources/syntax/#resource-types) * [Providers](https://opentofu.org/docs/v1.10/language/resources/syntax/#providers) * [Resource Arguments](https://opentofu.org/docs/v1.10/language/resources/syntax/#resource-arguments) * [Documentation for Resource Types](https://opentofu.org/docs/v1.10/language/resources/syntax/#documentation-for-resource-types) * [Resource Behavior](https://opentofu.org/docs/v1.10/language/resources/syntax/#resource-behavior) * [Removing Resources](https://opentofu.org/docs/v1.10/language/resources/syntax/#removing-resources) * [Meta-Arguments](https://opentofu.org/docs/v1.10/language/resources/syntax/#meta-arguments) * [Custom Condition Checks](https://opentofu.org/docs/v1.10/language/resources/syntax/#custom-condition-checks) * [Operation Timeouts](https://opentofu.org/docs/v1.10/language/resources/syntax/#operation-timeouts) --- # OCI Registry Integrations | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/oci_registries/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page OCI Registry Integrations ========================= Some of OpenTofu's features can be configured to interact with OCI Registries. These integrations are designed to support registries that implement [OCI Distribution v1.1.0](https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md) . Registries that implement earlier versions may work, depending on how strictly they validate submitted manifests, but we cannot officially support them because v1.1.0 is the first protocol version that includes explicit support for non-container-image artifacts. OCI Registry Credentials[​](https://opentofu.org/docs/v1.11/cli/oci_registries/#oci-registry-credentials "Direct link to OCI Registry Credentials") ---------------------------------------------------------------------------------------------------------------------------------------------------- By default, OpenTofu searches for OCI Registry credentials in the same locations as other tools in the OCI ecosystem, such as Docker CLI, Podman, Buildah, ORAS, etc. If you have already logged in to the registry you intend to use with the login facility from one of these programs then OpenTofu should discover and use the configured credentials automatically. If you need more control over the behavior, refer to [OCI Registry Credentials](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/) . OpenTofu Modules in OCI Registries[​](https://opentofu.org/docs/v1.11/cli/oci_registries/#opentofu-modules-in-oci-registries "Direct link to OpenTofu Modules in OCI Registries") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu supports OCI Registries as one of its many supported [module source address types](https://opentofu.org/docs/v1.11/language/modules/sources/) . No special configuration is required to enable this source address type aside from ensuring that you have configured whatever credentials are needed to communicate with the specified remote repository. For more information on how to create suitable artifacts for use as OpenTofu module packages, refer to [Module Packages in OCI Registries](https://opentofu.org/docs/v1.11/cli/oci_registries/module-package/) . OpenTofu Providers in OCI Registries[​](https://opentofu.org/docs/v1.11/cli/oci_registries/#opentofu-providers-in-oci-registries "Direct link to OpenTofu Providers in OCI Registries") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu supports OCI Registries as a secondary installation source for provider plugin packages. You can configure OpenTofu to retrieve some or all providers from an OCI Registry instead of from each provider's primary OpenTofu Provider Registry. For more information, refer to [Provider Mirrors in OCI Registries](https://opentofu.org/docs/v1.11/cli/oci_registries/provider-mirror/) . OpenTofu does not yet support using an OCI Registry as the _primary_ installation source for a provider, but we are hoping to allow that in a future version. * [OCI Registry Credentials](https://opentofu.org/docs/v1.11/cli/oci_registries/#oci-registry-credentials) * [OpenTofu Modules in OCI Registries](https://opentofu.org/docs/v1.11/cli/oci_registries/#opentofu-modules-in-oci-registries) * [OpenTofu Providers in OCI Registries](https://opentofu.org/docs/v1.11/cli/oci_registries/#opentofu-providers-in-oci-registries) --- # Provisioning Infrastructure with OpenTofu | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/run/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provisioning Infrastructure with OpenTofu ========================================= OpenTofu's primary function is to create, modify, and destroy infrastructure resources to match the desired state described in a [OpenTofu configuration](https://opentofu.org/docs/v1.11/language/) . When people refer to "running OpenTofu," they generally mean performing these provisioning actions in order to affect real infrastructure objects. The OpenTofu binary has many other subcommands for a wide variety of administrative actions, but these basic provisioning tasks are the core of OpenTofu. OpenTofu's provisioning workflow relies on three commands: `plan`, `apply`, and `destroy`. All of these commands require an [initialized](https://opentofu.org/docs/v1.11/cli/init/) working directory, and all of them act only upon the currently selected [workspace](https://opentofu.org/docs/v1.11/cli/workspaces/) . Planning[​](https://opentofu.org/docs/v1.11/cli/run/#planning "Direct link to Planning") ----------------------------------------------------------------------------------------- The `tofu plan` command evaluates a OpenTofu configuration to determine the desired state of all the resources it declares, then compares that desired state to the real infrastructure objects being managed with the current working directory and workspace. It uses state data to determine which real objects correspond to which declared resources, and checks the current state of each resource using the relevant infrastructure provider's API. Once it has determined the difference between the current state and the desired state, `tofu plan` presents a description of the changes necessary to achieve the desired state. It _does not_ perform any actual changes to real world infrastructure objects; it only presents a plan for making changes. Plans are usually run to validate configuration changes and confirm that the resulting actions are as expected. However, `tofu plan` can also save its plan as a runnable artifact, which `tofu apply` can use to carry out those exact changes. For details, see [the `tofu plan` command](https://opentofu.org/docs/v1.11/cli/commands/plan/) . Applying[​](https://opentofu.org/docs/v1.11/cli/run/#applying "Direct link to Applying") ----------------------------------------------------------------------------------------- The `tofu apply` command performs a plan just like `tofu plan` does, but then actually carries out the planned changes to each resource using the relevant infrastructure provider's API. It asks for confirmation from the user before making any changes, unless it was explicitly told to skip approval. By default, `tofu apply` performs a fresh plan right before applying changes, and displays the plan to the user when asking for confirmation. However, it can also accept a plan file produced by `tofu plan` in lieu of running a new plan. You can use this to reliably perform an exact set of pre-approved changes, even if the configuration or the state of the real infrastructure has changed in the minutes since the original plan was created. For details, see [the `tofu apply` command](https://opentofu.org/docs/v1.11/cli/commands/apply/) . Destroying[​](https://opentofu.org/docs/v1.11/cli/run/#destroying "Direct link to Destroying") ----------------------------------------------------------------------------------------------- The `tofu destroy` command destroys all of the resources being managed by the current working directory and workspace, using state data to determine which real world objects correspond to managed resources. Like `tofu apply`, it asks for confirmation before proceeding. A destroy behaves exactly like deleting every resource from the configuration and then running an apply, except that it doesn't require editing the configuration. This is more convenient if you intend to provision similar resources at a later date. For details, see [the `tofu destroy` command](https://opentofu.org/docs/v1.11/cli/commands/destroy/) . * [Planning](https://opentofu.org/docs/v1.11/cli/run/#planning) * [Applying](https://opentofu.org/docs/v1.11/cli/run/#applying) * [Destroying](https://opentofu.org/docs/v1.11/cli/run/#destroying) --- # Resource Graph | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/internals/graph/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Resource Graph ============== OpenTofu builds a [dependency graph](https://en.wikipedia.org/wiki/Dependency_graph) from the OpenTofu configurations, and walks this graph to generate plans, refresh state, and more. This page documents the details of what are contained in this graph, what types of nodes there are, and how the edges of the graph are determined. Advanced Topic! This page covers technical details of OpenTofu. You don't need to understand these details to effectively use OpenTofu. The details are documented here for those who wish to learn about them without having to go spelunking through the source code. For some background on graph theory, and a summary of how OpenTofu applies it, see the HashiCorp 2016 presentation [_Applying Graph Theory to Infrastructure as Code_](https://www.youtube.com/watch?v=Ce3RNfRbdZ0) . This presentation also covers some similar ideas to the following guide. Graph Nodes[​](https://opentofu.org/docs/v1.11/internals/graph/#graph-nodes "Direct link to Graph Nodes") ---------------------------------------------------------------------------------------------------------- There are only a handful of node types that can exist within the graph. We'll cover these first before explaining how they're determined and built: * **Resource Node** - Represents a single resource. If you have the `count` metaparameter set, then there will be one resource node for each count. The configuration, diff, state, etc. of the resource under change is attached to this node. * **Provider Configuration Node** - Represents the time to fully configure a provider. This is when the provider configuration block is given to a provider, such as AWS security credentials. * **Resource Meta-Node** - Represents a group of resources, but does not represent any action on its own. This is done for convenience on dependencies and making a prettier graph. This node is only present for resources that have a `count` parameter greater than 1. When visualizing a configuration with `tofu graph`, you can see all of these nodes present. Building the Graph[​](https://opentofu.org/docs/v1.11/internals/graph/#building-the-graph "Direct link to Building the Graph") ------------------------------------------------------------------------------------------------------------------------------- Building the graph is done in a series of sequential steps: 1. Resources nodes are added based on the configuration. If a diff (plan) or state is present, that meta-data is attached to each resource node. 2. Resources are mapped to provisioners if they have any defined. This must be done after all resource nodes are created so resources with the same provisioner type can share the provisioner implementation. 3. Explicit dependencies from the `depends_on` meta-parameter are used to create edges between resources. 4. If a state is present, any "orphan" resources are added to the graph. Orphan resources are any resources that are no longer present in the configuration but are present in the state file. Orphans never have any configuration associated with them, since the state file does not store configuration. 5. Resources are mapped to providers. Provider configuration nodes are created for these providers, and edges are created such that the resources depend on their respective provider being configured. 6. Interpolations are parsed in resource and provider configurations to determine dependencies. References to resource attributes are turned into dependencies from the resource with the interpolation to the resource being referenced. 7. Create a root node. The root node points to all resources and is created so there is a single root to the dependency graph. When traversing the graph, the root node is ignored. 8. If a diff is present, traverse all resource nodes and find resources that are being destroyed. These resource nodes are split into two: one node that destroys the resource and another that creates the resource (if it is being recreated). The reason the nodes must be split is because the destroy order is often different from the create order, and so they can't be represented by a single graph node. 9. Validate the graph has no cycles and has a single root. Walking the Graph[​](https://opentofu.org/docs/v1.11/internals/graph/#walking-the-graph "Direct link to Walking the Graph") ---------------------------------------------------------------------------------------------------------------------------- To walk the graph, a standard depth-first traversal is done. Graph walking is done in parallel: a node is walked as soon as all of its dependencies are walked. The amount of parallelism is limited using a semaphore to prevent too many concurrent operations from overwhelming the resources of the machine running OpenTofu. By default, up to 10 nodes in the graph will be processed concurrently. This number can be set using the `-parallelism` flag on the [plan](https://opentofu.org/docs/v1.11/cli/commands/plan/) , [apply](https://opentofu.org/docs/v1.11/cli/commands/apply/) , and [destroy](https://opentofu.org/docs/v1.11/cli/commands/destroy/) commands. Setting `-parallelism` is considered an advanced operation and should not be necessary for normal usage of OpenTofu. It may be helpful in certain special use cases or to help debug OpenTofu issues. Note that some providers (AWS, for example), handle API rate limiting issues at a lower level by implementing graceful backoff/retry in their respective API clients. For this reason, OpenTofu does not use this `parallelism` feature to address API rate limits directly. * [Graph Nodes](https://opentofu.org/docs/v1.11/internals/graph/#graph-nodes) * [Building the Graph](https://opentofu.org/docs/v1.11/internals/graph/#building-the-graph) * [Walking the Graph](https://opentofu.org/docs/v1.11/internals/graph/#walking-the-graph) --- # Workspaces | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/state/workspaces/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Workspaces ========== Each OpenTofu configuration has an associated [backend](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) that defines how OpenTofu executes operations and where OpenTofu stores persistent data, like [state](https://opentofu.org/docs/v1.10/language/state/purpose/) . The persistent data stored in the backend belongs to a workspace. The backend initially has only one workspace containing one OpenTofu state associated with that configuration. Some backends support multiple named workspaces, allowing multiple states to be associated with a single configuration. The configuration still has only one backend, but you can deploy multiple distinct instances of that configuration without configuring a new backend or changing authentication credentials. Backends Supporting Multiple Workspaces[​](https://opentofu.org/docs/v1.10/language/state/workspaces/#backends-supporting-multiple-workspaces "Direct link to Backends Supporting Multiple Workspaces") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can use multiple workspaces with the following backends: * [AzureRM](https://opentofu.org/docs/v1.10/language/settings/backends/azurerm/) * [Consul](https://opentofu.org/docs/v1.10/language/settings/backends/consul/) * [COS](https://opentofu.org/docs/v1.10/language/settings/backends/cos/) * [GCS](https://opentofu.org/docs/v1.10/language/settings/backends/gcs/) * [Kubernetes](https://opentofu.org/docs/v1.10/language/settings/backends/kubernetes/) * [Local](https://opentofu.org/docs/v1.10/language/settings/backends/local/) * [OSS](https://opentofu.org/docs/v1.10/language/settings/backends/oss/) * [Postgres](https://opentofu.org/docs/v1.10/language/settings/backends/pg/) * [Remote](https://opentofu.org/docs/v1.10/language/settings/backends/remote/) * [S3](https://opentofu.org/docs/v1.10/language/settings/backends/s3/) Using Workspaces[​](https://opentofu.org/docs/v1.10/language/state/workspaces/#using-workspaces "Direct link to Using Workspaces") ----------------------------------------------------------------------------------------------------------------------------------- Important Workspaces are not appropriate for system decomposition or deployments requiring separate credentials and access controls. Refer to [Use Cases](https://opentofu.org/docs/v1.10/cli/workspaces/#use-cases) in the OpenTofu CLI documentation for details and recommended alternatives. OpenTofu starts with a single, default workspace named `default` that you cannot delete. If you have not created a new workspace, you are using the default workspace in your OpenTofu working directory. When you run `tofu plan` in a new workspace, OpenTofu does not access existing resources in other workspaces. These resources still physically exist, but you must switch workspaces to manage them. Refer to the [OpenTofu CLI workspaces](https://opentofu.org/docs/v1.10/cli/workspaces/) documentation for full details about how to create and use workspaces. Current Workspace Interpolation[​](https://opentofu.org/docs/v1.10/language/state/workspaces/#current-workspace-interpolation "Direct link to Current Workspace Interpolation") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Within your OpenTofu configuration, you may include the name of the current workspace using the `${terraform.workspace}` interpolation sequence. This can be used anywhere interpolations are allowed. Referencing the current workspace is useful for changing behavior based on the workspace. For example, for non-default workspaces, it may be useful to spin up smaller cluster sizes. For example: Code Block resource "aws_instance" "example" { count = "${terraform.workspace == "default" ? 5 : 1}" # ... other arguments} Another popular use case is using the workspace name as part of naming or tagging behavior: Code Block resource "aws_instance" "example" { tags = { Name = "web - ${terraform.workspace}" } # ... other arguments} * [Backends Supporting Multiple Workspaces](https://opentofu.org/docs/v1.10/language/state/workspaces/#backends-supporting-multiple-workspaces) * [Using Workspaces](https://opentofu.org/docs/v1.10/language/state/workspaces/#using-workspaces) * [Current Workspace Interpolation](https://opentofu.org/docs/v1.10/language/state/workspaces/#current-workspace-interpolation) --- # Module Sources | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/modules/sources/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Module Sources ============== The `source` argument in [a `module` block](https://opentofu.org/docs/v1.10/language/modules/syntax/) tells OpenTofu where to find the source code for the desired child module. OpenTofu uses this during the module installation step of `tofu init` to download the source code to a directory on local disk so that other OpenTofu commands can use it. The module installer supports installation from a number of different source types. * [Local paths](https://opentofu.org/docs/v1.10/language/modules/sources/#local-paths) * [Module Registry](https://opentofu.org/docs/v1.10/language/modules/sources/#module-registry) * [GitHub](https://opentofu.org/docs/v1.10/language/modules/sources/#github) * [Bitbucket](https://opentofu.org/docs/v1.10/language/modules/sources/#bitbucket) * Generic [Git](https://opentofu.org/docs/v1.10/language/modules/sources/#generic-git-repository) , [Mercurial](https://opentofu.org/docs/v1.10/language/modules/sources/#generic-mercurial-repository) repositories * [OCI Distribution](https://opentofu.org/docs/v1.10/language/modules/sources/#oci-distribution-repository) repositories * [HTTP URLs](https://opentofu.org/docs/v1.10/language/modules/sources/#http-urls) * [S3 buckets](https://opentofu.org/docs/v1.10/language/modules/sources/#s3-bucket) * [GCS buckets](https://opentofu.org/docs/v1.10/language/modules/sources/#gcs-bucket) * [Modules in Package Sub-directories](https://opentofu.org/docs/v1.10/language/modules/sources/#modules-in-package-sub-directories) Each of these is described in the following sections. Module source addresses use a _URL-like_ syntax, but with extensions to support unambiguous selection of sources and additional features. We recommend using local file paths for closely-related modules used primarily for the purpose of factoring out repeated code elements, and using a native OpenTofu module registry for modules intended to be shared by multiple calling configurations. We support other sources so that you can potentially distribute OpenTofu modules internally with existing infrastructure. Many of the source types will make use of "ambient" credentials available when OpenTofu is run, such as from environment variables or credentials files in your home directory. This is covered in more detail in each of the following sections. We recommend placing each module that is intended to be re-usable in the root of its own repository or archive file, but it is also possible to [reference modules from subdirectories](https://opentofu.org/docs/v1.10/language/modules/sources/#modules-in-package-sub-directories) . Local Paths[​](https://opentofu.org/docs/v1.10/language/modules/sources/#local-paths "Direct link to Local Paths") ------------------------------------------------------------------------------------------------------------------- Local path references allow for factoring out portions of a configuration within a single source repository. Code Block module "consul" { source = "./consul"} A local path must begin with either `./` or `../` to indicate that a local path is intended, to distinguish from [a module registry address](https://opentofu.org/docs/v1.10/language/modules/sources/#module-registry) . Local paths are special in that they are not "installed" in the same sense that other sources are: the files are already present on local disk (possibly as a result of installing a parent module) and so can just be used directly. Their source code is automatically updated if the parent module is upgraded. Note that OpenTofu does not consider an _absolute_ filesystem path (starting with a slash, a drive letter, or similar) to be a local path. Instead, OpenTofu will treat that in a similar way as a remote module and copy it into the local module cache. An absolute path is a "package" in the sense described in [Modules in Package Sub-directories](https://opentofu.org/docs/v1.10/language/modules/sources/#modules-in-package-sub-directories) . We don't recommend using absolute filesystem paths to refer to modules, because it will tend to couple your configuration to the filesystem layout of a particular computer. Module Registry[​](https://opentofu.org/docs/v1.10/language/modules/sources/#module-registry "Direct link to Module Registry") ------------------------------------------------------------------------------------------------------------------------------- A module registry is the native way of distributing modules for use across multiple configurations, using an OpenTofu-specific protocol that has full support for module versioning. The [Public OpenTofu Registry](https://registry.opentofu.org/) is an index of modules shared publicly using this protocol. This public registry is the easiest way to get started with OpenTofu and find modules created by others in the community. You can also use a [private registry](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/) , either via [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software), or by running a custom service that implements [the module registry protocol](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/) . Modules on the public registry can be referenced using a registry source address of the form `//`, with each module's information page on the registry site including the exact address to use. Code Block module "consul" { source = "hashicorp/consul/aws" version = "0.1.0"} The above example will use the [Consul module for AWS](https://github.com/hashicorp/terraform-aws-consul) from a public registry. For modules hosted in other registries, prefix the source address with an additional `/` portion, giving the hostname of the private registry: Code Block module "consul" { source = "app.terraform.io/example-corp/k8s-cluster/azurerm" version = "1.1.0"} Registry modules support versioning. You can provide a specific version as shown in the above examples, or use flexible [version constraints](https://opentofu.org/docs/v1.10/language/modules/syntax/#version) . You can learn more about the registry at the [Module Registry documentation](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/) . To access modules from a private registry, you may need to configure an access token [in the CLI config](https://opentofu.org/docs/v1.10/cli/config/config-file/#credentials) . Use the same hostname as used in the module source string. For a private registry within [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software), use the same authentication token as you would use with the API or command-line clients. GitHub[​](https://opentofu.org/docs/v1.10/language/modules/sources/#github "Direct link to GitHub") ---------------------------------------------------------------------------------------------------- OpenTofu will recognize unprefixed `github.com` URLs and interpret them automatically as Git repository sources. Code Block module "consul" { source = "github.com/hashicorp/example"} The above address scheme will clone over HTTPS. To clone over SSH, use the following form: Code Block module "consul" { source = "[emailΒ protected]:hashicorp/example.git"} These GitHub schemes are treated as convenient aliases for [the general Git repository address scheme](https://opentofu.org/docs/v1.10/language/modules/sources/#generic-git-repository) , and so they obtain credentials in the same way and support the `ref` argument for selecting a specific revision. You will need to configure credentials in particular to access private repositories. Bitbucket[​](https://opentofu.org/docs/v1.10/language/modules/sources/#bitbucket "Direct link to Bitbucket") ------------------------------------------------------------------------------------------------------------- OpenTofu will recognize unprefixed `bitbucket.org` URLs and interpret them automatically as BitBucket repositories: Code Block module "consul" { source = "bitbucket.org/example-corp/tofu-consul-aws"} This shorthand works only for public repositories, because OpenTofu must access the BitBucket API to learn if the given repository uses Git or Mercurial. OpenTofu treats the result either as [a Git source](https://opentofu.org/docs/v1.10/language/modules/sources/#generic-git-repository) or [a Mercurial source](https://opentofu.org/docs/v1.10/language/modules/sources/#generic-mercurial-repository) depending on the repository type. See the sections on each version control type for information on how to configure credentials for private repositories and how to specify a specific revision to install. Generic Git Repository[​](https://opentofu.org/docs/v1.10/language/modules/sources/#generic-git-repository "Direct link to Generic Git Repository") ---------------------------------------------------------------------------------------------------------------------------------------------------- Arbitrary Git repositories can be used by prefixing the address with the special `git::` prefix. After this prefix, any valid [Git URL](https://git-scm.com/docs/git-clone#_git_urls) can be specified to select one of the protocols supported by Git. For example, to use HTTPS or SSH: Code Block module "vpc" { source = "git::https://example.com/vpc.git"}module "storage" { source = "git::ssh://[emailΒ protected]/storage.git"} OpenTofu installs modules from Git repositories by running `git clone`, and so it will respect any local Git configuration set on your system, including credentials. To access a non-public Git repository, configure Git with suitable credentials for that repository. If you use the SSH protocol then any configured SSH keys will be used automatically. This is the most common way to access non-public Git repositories from automated systems because it allows access to private repositories without interactive prompts. If using the HTTP/HTTPS protocol, or any other protocol that uses username/password credentials, configure [Git Credentials Storage](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage) to select a suitable source of credentials for your environment. ### Selecting a Revision[​](https://opentofu.org/docs/v1.10/language/modules/sources/#selecting-a-revision "Direct link to Selecting a Revision") By default, OpenTofu will clone and use the default branch (referenced by `HEAD`) in the selected repository. You can override this using the `ref` argument. The value of the `ref` argument can be any reference that would be accepted by the `git checkout` command, such as branch, SHA-1 hash (short or full), or tag names. For a full list of the possible values, see [Git Tools - Revision Selection](https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection#_single_revisions) in [the Git Book](https://git-scm.com/book/en/v2) . Code Block # select a specific tagmodule "vpc" { source = "git::https://example.com/vpc.git?ref=v1.2.0"}# directly select a commit using its SHA-1 hashmodule "storage" { source = "git::https://example.com/storage.git?ref=51d462976d84fdea54b47d80dcabbf680badcdb8"} ### Shallow Clone[​](https://opentofu.org/docs/v1.10/language/modules/sources/#shallow-clone "Direct link to Shallow Clone") For larger repositories you may prefer to make only a shallow clone in order to reduce the time taken to retrieve the remote repository. The `depth` URL argument corresponds to [the `--depth` argument to `git clone`](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt) , telling Git to create a shallow clone with the history truncated to only the specified number of commits. However, because shallow clone requires different Git protocol behavior, setting the `depth` argument makes OpenTofu pass your [`ref` argument](https://opentofu.org/docs/v1.10/language/modules/sources/#selecting-a-revision) , if any, to [the `--branch` argument to `git clone`](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---branchltnamegt) instead. That means it must specify a named branch or tag known to the remote repository, and that raw commit IDs are not acceptable. Because OpenTofu only uses the most recent selected commit to find the source code of your specified module, it is not typically useful to set `depth` to any value other than `1`. ### "scp-like" address syntax[​](https://opentofu.org/docs/v1.10/language/modules/sources/#scp-like-address-syntax "Direct link to "scp-like" address syntax") When using Git over SSH, we recommend using the `ssh://`\-prefixed URL form for consistency with all of the other URL-like git address forms. You may opt to use the alternative "scp-like" syntax instead, in which case you must omit the `ssh://` scheme part and include only the `git::` part. For example: Code Block module "storage" { source = "git::[emailΒ protected]:storage.git"} If you use the `ssh://` URL scheme then OpenTofu will assume that the colon marks the beginning of a port number, rather than the beginning of the path. This matches how Git itself interprets these different forms, aside from the OpenTofu-specific `git::` selector prefix. Generic Mercurial Repository[​](https://opentofu.org/docs/v1.10/language/modules/sources/#generic-mercurial-repository "Direct link to Generic Mercurial Repository") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can use arbitrary Mercurial repositories by prefixing the address with the special `hg::` prefix. After this prefix, any valid [Mercurial URL](https://www.mercurial-scm.org/repo/hg/help/urls) can be specified to select one of the protocols supported by Mercurial. Code Block module "vpc" { source = "hg::http://example.com/vpc.hg"} OpenTofu installs modules from Mercurial repositories by running `hg clone`, and so it will respect any local Mercurial configuration set on your system, including credentials. To access a non-public repository, configure Mercurial with suitable credentials for that repository. If you use the SSH protocol then any configured SSH keys will be used automatically. This is the most common way to access non-public Mercurial repositories from automated systems because it allows access to private repositories without interactive prompts. ### Selecting a Revision[​](https://opentofu.org/docs/v1.10/language/modules/sources/#selecting-a-revision-1 "Direct link to Selecting a Revision") You can select a non-default branch or tag using the optional `ref` argument: Code Block module "vpc" { source = "hg::http://example.com/vpc.hg?ref=v1.2.0"} OCI Distribution Repository[​](https://opentofu.org/docs/v1.10/language/modules/sources/#oci-distribution-repository "Direct link to OCI Distribution Repository") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- The OCI Distribution protocol is a generalization of the protocol originally used by Docker for distributing container images. OpenTofu can install module packages from specially-formatted artifacts published into repositories in OCI Registries. Code Block module "example" { source = "oci://example.com/repository-name"} The domain name specified immediately after the `oci://` prefix is the OCI Registry domain name. The remainder of the address specifies a specific repository name within that repository. If your specified OCI Registry requires authentication credentials, refer to [OCI Registry Credentials](https://opentofu.org/docs/v1.10/cli/oci_registries/credentials/) . ### Selecting a Tag or Digest[​](https://opentofu.org/docs/v1.10/language/modules/sources/#selecting-a-tag-or-digest "Direct link to Selecting a Tag or Digest") By default, OpenTofu attempts to retrieve the artifact associated with the remote tag named "latest". You can select a different artifact using one of the following arguments in the query string: * `tag` specifies a different tag name to use. * `digest` directly specifies the digest of the manifest of the desired artifact, totally ignoring the tags defined in the repository. Only one of these arguments at a time can be used in a valid source address. For example, to select a tag named `v1.0.0`: Code Block module "example" { source = "oci://example.com/repository-name?tag=v1.0.0"} ### Building a module package artifact[​](https://opentofu.org/docs/v1.10/language/modules/sources/#building-a-module-package-artifact "Direct link to Building a module package artifact") For more information on the manifest structure that OpenTofu expects for module package artifacts, refer to [Module Packages in OCI Registries](https://opentofu.org/docs/v1.10/cli/oci_registries/module-package/) . HTTP URLs[​](https://opentofu.org/docs/v1.10/language/modules/sources/#http-urls "Direct link to HTTP URLs") ------------------------------------------------------------------------------------------------------------- When you use an HTTP or HTTPS URL, OpenTofu will make a `GET` request to the given URL, which can return _another_ source address. This indirection allows using HTTP URLs as a sort of "vanity redirect" over a more complicated module source address. OpenTofu will append an additional query string argument `tofu-get=1` to the given URL before sending the `GET` request, allowing the server to optionally return a different result when OpenTofu is requesting it. If the response is successful (`200`\-range status code), OpenTofu looks in the following locations in order for the next address to access: * The value of a response header field named `X-Terraform-Get`. * If the response is an HTML page, a `meta` element with the name `tofu-get`: Code Block In either case, the result is interpreted as another module source address using one of the forms documented elsewhere on this page. If an HTTP/HTTPS URL requires authentication credentials, use a `.netrc` file to configure the credentials. By default, OpenTofu searches for the `.netrc` file in your HOME directory. However, you can override the default filesystem location by setting the `NETRC` environment variable. For information on the `.netrc` format, refer to [the documentation for using it in `curl`](https://everything.curl.dev/usingcurl/netrc) . ### Fetching archives over HTTP[​](https://opentofu.org/docs/v1.10/language/modules/sources/#fetching-archives-over-http "Direct link to Fetching archives over HTTP") As a special case, if OpenTofu detects that the URL has a common file extension associated with an archive file format then it will bypass the special `tofu-get=1` redirection described above and instead just use the contents of the referenced archive as the module source code: Code Block module "vpc" { source = "https://example.com/vpc-module.zip"} The extensions that OpenTofu recognizes for this special behavior are: * `zip` * `tar.bz2` and `tbz2` * `tar.gz` and `tgz` * `tar.xz` and `txz` If your URL _doesn't_ have one of these extensions but refers to an archive anyway, use the `archive` argument to force this interpretation: Code Block module "vpc" { source = "https://example.com/vpc-module?archive=zip"} Note If the content of the archive file is a directory, you will need to include that directory in the module source. Read the section on [Modules in Package Sub-directories](https://opentofu.org/docs/v1.10/language/modules/sources/#modules-in-package-sub-directories) for more information. S3 Bucket[​](https://opentofu.org/docs/v1.10/language/modules/sources/#s3-bucket "Direct link to S3 Bucket") ------------------------------------------------------------------------------------------------------------- You can use archives stored in S3 as module sources using the special `s3::` prefix, followed by [an S3 bucket object URL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html) . Code Block module "consul" { source = "s3::https://s3-eu-west-1.amazonaws.com/examplecorp-tofu-modules/vpc.zip"} Note Buckets in AWS's us-east-1 region must use the hostname `s3.amazonaws.com` (instead of `s3-us-east-1.amazonaws.com`). The `s3::` prefix causes OpenTofu to use AWS-style authentication when accessing the given URL. As a result, this scheme may also work for other services that mimic the S3 API, as long as they handle authentication in the same way as AWS. The resulting object must be an archive with one of the same file extensions as for [archives over standard HTTP](https://opentofu.org/docs/v1.10/language/modules/sources/#fetching-archives-over-http) . OpenTofu will extract the archive to obtain the module source tree. The module installer looks for AWS credentials in the following locations, preferring those earlier in the list when multiple are available: * The `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. * The default profile in the `.aws/credentials` file in your home directory. * If running on an EC2 instance, temporary credentials associated with the instance's IAM Instance Profile. GCS Bucket[​](https://opentofu.org/docs/v1.10/language/modules/sources/#gcs-bucket "Direct link to GCS Bucket") ---------------------------------------------------------------------------------------------------------------- You can use archives stored in Google Cloud Storage as module sources using the special `gcs::` prefix, followed by [a GCS bucket object URL](https://cloud.google.com/storage/docs/request-endpoints#typical) . For example * `gcs::https://www.googleapis.com/storage/v1/BUCKET_NAME/PATH_TO_MODULE` * `gcs::https://www.googleapis.com/storage/v1/BUCKET_NAME/PATH/TO/module.zip` Code Block module "consul" { source = "gcs::https://www.googleapis.com/storage/v1/modules/foomodule.zip"} The module installer uses Google Cloud SDK to authenticate with GCS. You can use any of the following methods to set Google Cloud Platform credentials: * Set the `GOOGLE_OAUTH_ACCESS_TOKEN` environment variable to a raw Google Cloud Platform OAuth access token. * Enter the path of your service account key file in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. * If you're running OpenTofu from a GCE instance, default credentials are automatically available. See [Creating and Enabling Service Accounts](https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances) for Instances for more details. * On your computer, you can make your Google identity available by running `gcloud auth application-default login`. Modules in Package Sub-directories[​](https://opentofu.org/docs/v1.10/language/modules/sources/#modules-in-package-sub-directories "Direct link to Modules in Package Sub-directories") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When the source of a module is a version control repository or archive file (generically, a "package"), the module itself may be in a sub-directory relative to the root of the package. A special double-slash syntax is interpreted by OpenTofu to indicate that the remaining path after that point is a sub-directory within the package. For example: * `hashicorp/consul/aws//modules/consul-cluster` * `git::https://example.com/network.git//modules/vpc` * `oci://example.com/repository-name//modules/vpc` * `https://example.com/network-module.zip//modules/vpc` * `s3::https://s3-eu-west-1.amazonaws.com/examplecorp-tofu-modules/network.zip//modules/vpc` If the source address has arguments, such as the `ref` argument supported for the version control sources, the sub-directory portion must be _before_ those arguments: * `git::https://example.com/network.git//modules/vpc?ref=v1.2.0` * `github.com/hashicorp/example//modules/vpc?ref=v1.2.0` * `oci://example.com/repository-name//modules/vpc?tag=v1.2.0` OpenTofu will still extract the entire package to local disk, but will read the module from the subdirectory. As a result, it is safe for a module in a sub-directory of a package to use [a local path](https://opentofu.org/docs/v1.10/language/modules/sources/#local-paths) to another module as long as it is in the _same_ package. Support for Variable and Local Evaluation[​](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation "Direct link to Support for Variable and Local Evaluation") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- As projects grow in complexity and requirements, it is prudent to consider using locals and variables in the module source and version fields. Many organizations utilize the mono-repo pattern for modules: Code Block locals { modules_repo = "github.com/myorg/tofu-modules/" modules_version = "?ref=v1.20.4"}module "storage" { source = "${local.modules_repo}/storage${local.modules_version}"}module "compute" { source = "${local.modules_repo}/compute${local.modules_version}"} It is quite easy to then update the version for a patch release, or to switch to a fork of the repository. Note The source and version fields may not contain any references to data in the state or provider defined functions. All values must be able to be resolved during `tofu init` before the state is available. * [Local Paths](https://opentofu.org/docs/v1.10/language/modules/sources/#local-paths) * [Module Registry](https://opentofu.org/docs/v1.10/language/modules/sources/#module-registry) * [GitHub](https://opentofu.org/docs/v1.10/language/modules/sources/#github) * [Bitbucket](https://opentofu.org/docs/v1.10/language/modules/sources/#bitbucket) * [Generic Git Repository](https://opentofu.org/docs/v1.10/language/modules/sources/#generic-git-repository) * [Selecting a Revision](https://opentofu.org/docs/v1.10/language/modules/sources/#selecting-a-revision) * [Shallow Clone](https://opentofu.org/docs/v1.10/language/modules/sources/#shallow-clone) * ["scp-like" address syntax](https://opentofu.org/docs/v1.10/language/modules/sources/#scp-like-address-syntax) * [Generic Mercurial Repository](https://opentofu.org/docs/v1.10/language/modules/sources/#generic-mercurial-repository) * [Selecting a Revision](https://opentofu.org/docs/v1.10/language/modules/sources/#selecting-a-revision-1) * [OCI Distribution Repository](https://opentofu.org/docs/v1.10/language/modules/sources/#oci-distribution-repository) * [Selecting a Tag or Digest](https://opentofu.org/docs/v1.10/language/modules/sources/#selecting-a-tag-or-digest) * [Building a module package artifact](https://opentofu.org/docs/v1.10/language/modules/sources/#building-a-module-package-artifact) * [HTTP URLs](https://opentofu.org/docs/v1.10/language/modules/sources/#http-urls) * [Fetching archives over HTTP](https://opentofu.org/docs/v1.10/language/modules/sources/#fetching-archives-over-http) * [S3 Bucket](https://opentofu.org/docs/v1.10/language/modules/sources/#s3-bucket) * [GCS Bucket](https://opentofu.org/docs/v1.10/language/modules/sources/#gcs-bucket) * [Modules in Package Sub-directories](https://opentofu.org/docs/v1.10/language/modules/sources/#modules-in-package-sub-directories) * [Support for Variable and Local Evaluation](https://opentofu.org/docs/v1.10/language/modules/sources/#support-for-variable-and-local-evaluation) --- # Import | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/import/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Import ====== OpenTofu can import existing infrastructure resources. This functionality lets you bring existing resources under OpenTofu management. Note OpenTofu supports `import` blocks. Unlike the `tofu import` command, you can use `import` blocks to import more than one resource at a time, and you can review imports as part of your normal plan and apply workflow. [Learn more about `import` blocks](https://opentofu.org/docs/v1.11/language/import/) . State Only[​](https://opentofu.org/docs/v1.11/cli/import/#state-only "Direct link to State Only") -------------------------------------------------------------------------------------------------- Warning OpenTofu expects that each remote object is bound to a _single_ resource address. You should import each remote object to _one_ OpenTofu resource address. If you import the same object multiple times, OpenTofu may exhibit unwanted behavior. See [State](https://opentofu.org/docs/v1.11/language/state/) for more details. The `tofu import` CLI command can only import resources into the [state](https://opentofu.org/docs/v1.11/language/state/) . Importing via the CLI does _not_ generate configuration. If you want to generate the accompanying configuration for imported resources, [use the `import` block instead](https://opentofu.org/docs/v1.11/language/import/) . Before you run `tofu import` you must manually write a `resource` configuration block for the resource. The resource block describes where OpenTofu should map the imported object. Cloud Backend[​](https://opentofu.org/docs/v1.11/cli/import/#cloud-backend "Direct link to Cloud Backend") ----------------------------------------------------------------------------------------------------------- When you use OpenTofu on the command line with a cloud backend, many commands like `apply` run inside your cloud backend's environment. However, the `import` command runs locally, so it does not have access to information from the cloud backend. To successfully perform an import, you may need to set local variables equivalent to any remote workspace variables in the cloud backend. * [State Only](https://opentofu.org/docs/v1.11/cli/import/#state-only) * [Cloud Backend](https://opentofu.org/docs/v1.11/cli/import/#cloud-backend) --- # Import Usage | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/import/usage/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Import Usage ============ Use the `tofu import` command to import existing infrastructure to OpenTofu state. The `tofu import` command can only import one resource at a time. It cannot simultaneously import an entire collection of resources, like an AWS VPC. Warning OpenTofu expects that each remote object it is managing will be bound to only one resource address, which is normally guaranteed by OpenTofu itself having created all objects. If you import existing objects into OpenTofu, be careful to import each remote object to only one OpenTofu resource address. If you import the same object multiple times, OpenTofu may exhibit unwanted behavior. For more information on this assumption, see [the State section](https://opentofu.org/docs/v1.11/cli/state/) . To import a resource, first write a resource block for it in your configuration, establishing the name by which it will be known to OpenTofu: Code Block resource "aws_instance" "example" { # ...instance configuration...} The name "example" here is local to the module where it is declared and is chosen by the configuration author. This is distinct from any ID issued by the remote system, which may change over time while the resource name remains constant. If desired, you can leave the body of the resource block blank for now and return to fill it in once the instance is imported. Now `tofu import` can be run to attach an existing instance to this resource configuration: Code Block $ tofu import aws_instance.example i-abcd1234 This command locates the AWS EC2 instance with ID `i-abcd1234`. Then it attaches the existing settings of the instance, as described by the EC2 API, to the name `aws_instance.example` of a module. In this example the module path implies that the root module is used. Finally, the mapping is saved in the OpenTofu state. It is also possible to import to resources in child modules, using their paths, and to single instances of a resource with `count` or `for_each` set. See [_Resource Addressing_](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/) for more details on how to specify a target resource. The syntax of the given ID is dependent on the resource type being imported. For example, AWS instances use an opaque ID issued by the EC2 API, but AWS Route53 Zones use the domain name itself. Consult the documentation for each importable resource for details on what form of ID is required. As a result of the above command, the resource is recorded in the state file. You can now run `tofu plan` to see how the configuration compares to the imported resource, and make any adjustments to the configuration to align with the current (or desired) state of the imported object. Complex Imports[​](https://opentofu.org/docs/v1.11/cli/import/usage/#complex-imports "Direct link to Complex Imports") ----------------------------------------------------------------------------------------------------------------------- The above import is considered a "simple import": one resource is imported into the state file. An import may also result in a "complex import" where multiple resources are imported. For example, an AWS network ACL imports an `aws_network_acl` but also one `aws_network_acl_rule` for each rule. In this scenario, the secondary resources will not already exist in configuration, so it is necessary to consult the import output and create a `resource` block in configuration for each secondary resource. If this is not done, OpenTofu will plan to destroy the imported objects on the next run. If you want to rename or otherwise move the imported resources, the [state management commands](https://opentofu.org/docs/v1.11/cli/commands/state/) can be used. * [Complex Imports](https://opentofu.org/docs/v1.11/cli/import/usage/#complex-imports) --- # Provider Network Mirror Protocol | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provider Network Mirror Protocol ================================ The provider network mirror protocol is an optional protocol which you can implement to provide an alternative installation source for Terraform providers, regardless of their origin registries. OpenTofu uses network mirrors only if you activate them explicitly in [the CLI configuration's `provider_installation` block](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation) . When enabled, a network mirror can serve providers belonging to any registry hostname, which can allow an organization to serve all of the OpenTofu providers they intend to use from an internal server, rather than from each provider's origin registry. This is _not_ the protocol that should be implemented by a host intending to serve as an origin registry for OpenTofu Providers. To provide an origin registry (whose hostname would then be included in the source addresses of the providers it hosts), implement [the provider registry protocol](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/) instead. Provider Addresses[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#provider-addresses "Direct link to Provider Addresses") ---------------------------------------------------------------------------------------------------------------------------------------------------------- Each OpenTofu provider has an associated address which uniquely identifies it within OpenTofu. A provider address has the syntax `hostname/namespace/type`, which is described in more detail in [the Provider Requirements documentation](https://opentofu.org/docs/v1.11/language/providers/requirements/) . By default, the `hostname` portion of a provider address serves both as part of its unique identifier _and_ as the location of the registry to retrieve it from. However, when you configure OpenTofu to install providers from a network mirror, the `hostname` serves _only_ as an identifier and no longer as an installation source. A provider mirror can therefore serve providers belonging to a variety of different provider registry hostnames, including providers from the public OpenTofu Registry at `registry.opentofu.org`, from a single server. In the relative URL patterns later in this document, the placeholder `:hostname` refers to the hostname from the address of the provider being requested, not the hostname where the provider network mirror is deployed. Protocol Base URL[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#protocol-base-url "Direct link to Protocol Base URL") ------------------------------------------------------------------------------------------------------------------------------------------------------- Most OpenTofu-native services use [the remote service discovery protocol](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/) so that the physical location of the endpoints can potentially be separated from the hostname used in identifiers. The Provider Network Mirror protocol does _not_ use the service discovery indirection, because a network mirror location is only a physical location and is never used as part of the identifier of a dependency in a OpenTofu configuration. Instead, the provider installation section of the CLI configuration accepts a base URL directly. The given URL must use the scheme `https:`, and should end with a trailing slash so that the relative URLs of the individual operation endpoints will be resolved beneath it. Code Block provider_installation { network_mirror { url = "https://tofu.example.com/providers/" }} OpenTofu uses the base URL only as a stem to resolve the operation endpoint URLs against, and so it will never access the base URL directly. You can therefore, if desired, publish human-readable usage documentation for your network mirror at that URL. The following sections describe the various operations that a provider network mirror server must implement to be compatible with OpenTofu CLI's provider installer. The indicated URLs are all relative to the given base URL, as described above. The URLs are shown with the convention that a path portion with a colon `:` prefix is a placeholder for a dynamically-selected value, while all other path portions are literal. For example, in `:hostname/:namespace/:type/index.json`, the first three path portions are placeholders while the third is literally the string "index.json". The example requests in the following sections will assume the example mirror base URL from the above CLI configuration example. ### Authentication[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#authentication "Direct link to Authentication") If the CLI configuration includes [credentials](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials) for the hostname given in the network mirror base URL, OpenTofu will include those credentials in its requests for operations described below. If the given URL uses a non-standard port number (other than 443) then the credentials must be associated with a hostname that includes the port number, such as `tofu.example.com:8443`. OpenTofu does _not_ send credentials when retrieving the archives whose URLs are given in the "List Available Installation Packages" response below. If a particular mirror considers the distribution packages themselves to be sensitive then it must use cryptographically-secure, user-specific, and time-limited URLs in the metadata response. Strategies for doing so are out of scope of this protocol documentation. List Available Versions[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#list-available-versions "Direct link to List Available Versions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This operation determines which versions are currently available for a particular provider. | Method | Path | Produces | | --- | --- | --- | | `GET` | `:hostname/:namespace/:type/index.json` | `application/json` | ### Parameters[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#parameters "Direct link to Parameters") * `hostname` (required): the hostname portion of the address of the requested provider. * `namespace` (required): the namespace portion of the address of the requested provider. * `type` (required): the type portion of the address of the requested provider. ### Sample Request[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#sample-request "Direct link to Sample Request") Code Block curl 'https://tofu.example.com/providers/registry.tofu.io/hashicorp/random/index.json' ### Sample Response[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#sample-response "Direct link to Sample Response") Code Block { "versions": { "2.0.0": {}, "2.0.1": {} }} ### Response Properties[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#response-properties "Direct link to Response Properties") A successful result is a JSON object containing a single property `versions`, which must be a JSON object. Each of the property names of the `versions` object represents an available version number. The property values must be objects, but no properties are defined for those objects. We recommend leaving those objects empty for forward compatibility. Return `404 Not Found` to signal that the mirror does not have a provider with the given address. List Available Installation Packages[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#list-available-installation-packages "Direct link to List Available Installation Packages") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This operation returns download URLs and associated metadata for the distribution packages for a particular version of a provider. Each distribution package is associated with a particular operating system and architecture. A network mirror may host only a subset of the available packages for a provider version, if the users of the mirror are known to all use only a subset of the target platforms that OpenTofu supports. OpenTofu CLI uses this operation after it has selected the newest available version matching the configured version constraints, in order to find a zip archive containing the plugin itself. | Method | Path | Produces | | --- | --- | --- | | `GET` | `:hostname/:namespace/:type/:version.json` | `application/json` | ### Parameters[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#parameters-1 "Direct link to Parameters") * `hostname` (required): the hostname portion of the address of the requested provider. * `namespace` (required): the namespace portion of the address of the requested provider. * `type` (required): the type portion of the address of the requested provider. * `version` (required): the version selected to download. This will exactly match one of the version strings returned from a previous call to [List Available Versions](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#list-available-versions) . ### Sample Request[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#sample-request-1 "Direct link to Sample Request") Code Block curl 'https://tofu.example.com/providers/registry.tofu.io/hashicorp/random/2.0.0.json' ### Sample Response[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#sample-response-1 "Direct link to Sample Response") Code Block { "archives": { "darwin_amd64": { "url": "terraform-provider-random_2.0.0_darwin_amd64.zip", "hashes": [ "h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=" ] }, "linux_amd64": { "url": "terraform-provider-random_2.0.0_linux_amd64.zip", "hashes": [ "h1:lCJCxf/LIowc2IGS9TPjWDyXY4nOmdGdfcwwDQCOURQ=" ] } }} ### Response Properties[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#response-properties-1 "Direct link to Response Properties") A successful result is a JSON object with a property called `archives`, which must be a JSON object. Each of the property names of the `archives` object is a target platform identifier, which consists of an operating system and architecture concatenated with an underscore (`_`). Each property value in the `archives` object is itself a nested object with the following properties: * `url` (required): a string specifying the URL from which OpenTofu should download the `.zip` archive containing the requested provider plugin version. OpenTofu resolves the URL relative to the URL from which the current JSON document was returned, so the examples above containing only a filename would cause OpenTofu to construct a URL like: Code Block https://tofu.example.com/providers/registry.opentofu.org/hashicorp/random/terraform-provider-random_2.0.0_darwin_amd64.zip * `hashes` (optional): a JSON array of strings containing one or more hash values for the indicated archive. These hashes use OpenTofu's provider package hashing algorithm. At present, the easiest way to populate these is to construct a mirror's JSON indices using the `tofu providers mirror` command, as described in a later section, which will include the calculated hashes of each provider. If the response includes at least one hash, OpenTofu will select the hash whose algorithm it considers to be strongest and verify that the downloaded package matches that hash. If the response does not include a `hashes` property then OpenTofu will install the indicated archive with no verification. OpenTofu CLI will only attempt to download versions that it has previously seen in response to [List Available Versions](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#list-available-versions) . Provider Mirror as a Static Website[​](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#provider-mirror-as-a-static-website "Direct link to Provider Mirror as a Static Website") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The provider mirror protocol is designed so that it can potentially be implemented by placing files on typical static website hosting services. When using this strategy, implement the JSON index responses described above as `.json` files in the appropriate nested subdirectories, and ensure that your system is configured to serve `.json` files with the `application/json` media type. As a convenience, OpenTofu CLI includes [the `tofu providers mirror` subcommand](https://opentofu.org/docs/v1.11/cli/commands/providers/mirror/) , which will analyze the current configuration for the providers it requires, download the packages for those providers from their origin registries, and place them into a local directory suitable for use as a mirror. The `tofu providers mirror` subcommand also generates `index.json` and version-specific `.json` files that can, when placed in a static website hosting system, produce responses compatible with the provider mirror protocol. If you wish to create a mirror with providers for a number of different OpenTofu configurations, run `tofu providers mirror` in each configuration in turn while providing the same output directory each time. OpenTofu will then merge together all of the requirements into a single set of JSON indices. * [Provider Addresses](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#provider-addresses) * [Protocol Base URL](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#protocol-base-url) * [Authentication](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#authentication) * [List Available Versions](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#list-available-versions) * [Parameters](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#parameters) * [Sample Request](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#sample-request) * [Sample Response](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#sample-response) * [Response Properties](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#response-properties) * [List Available Installation Packages](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#list-available-installation-packages) * [Parameters](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#parameters-1) * [Sample Request](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#sample-request-1) * [Sample Response](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#sample-response-1) * [Response Properties](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#response-properties-1) * [Provider Mirror as a Static Website](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/#provider-mirror-as-a-static-website) --- # State | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/state/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page State ===== OpenTofu must store state about your managed infrastructure and configuration. This state is used by OpenTofu to map real world resources to your configuration, keep track of metadata, and to improve performance for large infrastructures. This state is stored by default in a local file named "terraform.tfstate", but we recommend storing it in [TACOS](https://opentofu.org/docs/v1.10/intro/tacos/) (TF Automation and Collaboration Software) to version, encrypt, and securely share it with your team. OpenTofu uses state to determine which changes to make to your infrastructure. Prior to any operation, OpenTofu does a [refresh](https://opentofu.org/docs/v1.10/cli/commands/refresh/) to update the state with the real infrastructure. The primary purpose of OpenTofu state is to store bindings between objects in a remote system and resource instances declared in your configuration. When OpenTofu creates a remote object in response to a change of configuration, it will record the identity of that remote object against a particular resource instance, and then potentially update or delete that object in response to future configuration changes. For more information on why OpenTofu requires state and why OpenTofu cannot function without state, please see the page [state purpose](https://opentofu.org/docs/v1.10/language/state/purpose/) . Inspection and Modification[​](https://opentofu.org/docs/v1.10/language/state/#inspection-and-modification "Direct link to Inspection and Modification") --------------------------------------------------------------------------------------------------------------------------------------------------------- While the format of the state files are just JSON, direct file editing of the state is discouraged. OpenTofu provides the [tofu state](https://opentofu.org/docs/v1.10/cli/commands/state/) command to perform basic modifications of the state using the CLI. The CLI usage and output of the state commands is structured to be friendly for Unix tools such as grep, awk, etc. Additionally, the CLI insulates users from any format changes within the state itself. The OpenTofu project will keep the CLI working while the state format underneath it may shift. OpenTofu expects a one-to-one mapping between configured resource instances and remote objects. Normally that is guaranteed by OpenTofu being the one to create each object and record its identity in the state, or to destroy an object and then remove the binding for it. If you add or remove bindings in the state by other means, such as by importing externally-created objects with `tofu import`, or by asking OpenTofu to "forget" an existing object with `tofu state rm`, you'll then need to ensure for yourself that this one-to-one rule is followed, such as by manually deleting an object that you asked OpenTofu to "forget", or by re-importing it to bind it to some other resource instance. Format[​](https://opentofu.org/docs/v1.10/language/state/#format "Direct link to Format") ------------------------------------------------------------------------------------------ State snapshots are stored in JSON format and new OpenTofu versions are generally backward compatible with state snapshots produced by earlier versions. However, the state format is subject to change in new OpenTofu versions, so if you build software that parses or modifies it directly you should expect to perform ongoing maintenance of that software as the state format evolves in new versions. Alternatively, there are several integration points which produce JSON output that is specifically intended for consumption by external software: * [The `tofu output` command](https://opentofu.org/docs/v1.10/cli/commands/output/) has a `-json` option, for obtaining either the full set of root module output values or a specific named output value from the latest state snapshot. * [The `tofu show` command](https://opentofu.org/docs/v1.10/cli/commands/show/) has a `-json` option for inspecting the latest state snapshot in full, and also for inspecting saved plan files which include a copy of the prior state at the time the plan was made. A typical way to use these in situations where OpenTofu is running in automation is to run them immediately after a successful `tofu apply` to obtain a representation of the latest state snapshot, and then store that result as an artifact associated with the automated run so that other software can potentially consume it without needing to run OpenTofu itself. * [Inspection and Modification](https://opentofu.org/docs/v1.10/language/state/#inspection-and-modification) * [Format](https://opentofu.org/docs/v1.10/language/state/#format) --- # Recovering from State Disasters | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/state/recover/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Recovering from State Disasters =============================== If something has gone horribly wrong (possibly due to accidents when performing other state manipulation actions), you might need to take drastic actions with your state data. * [The `tofu force-unlock` command](https://opentofu.org/docs/v1.11/cli/commands/force-unlock/) can override the protections OpenTofu uses to prevent two processes from modifying state at the same time. You might need this if a OpenTofu process (like a normal apply) is unexpectedly terminated (like by the complete destruction of the VM it's running in) before it can release its lock on the state backend. Do not run this until you are completely certain what happened to the process that caused the lock to get stuck. * [The `tofu state pull` command](https://opentofu.org/docs/v1.11/cli/commands/state/pull/) and [the `tofu state push` command](https://opentofu.org/docs/v1.11/cli/commands/state/push/) can directly read and write entire state files from and to the configured backend. You might need this for obtaining or restoring a state backup. --- # Inspecting State | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/state/inspect/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Inspecting State ================ OpenTofu includes some commands for reading and updating state without taking any other actions. * [The `tofu state list` command](https://opentofu.org/docs/v1.11/cli/commands/state/list/) shows the resource addresses for every resource OpenTofu knows about in a configuration, optionally filtered by partial resource address. * [The `tofu state show` command](https://opentofu.org/docs/v1.11/cli/commands/state/show/) displays detailed state data about one resource. * [The `tofu refresh` command](https://opentofu.org/docs/v1.11/cli/commands/refresh/) updates state data to match the real-world condition of the managed resources. This is done automatically during plans and applies, but not when interacting with state directly. --- # Moving Resources | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/state/move/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Moving Resources ================ OpenTofu's state associates each real-world object with a configured resource at a specific [resource address](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/) . This is seamless when changing a resource's attributes, but OpenTofu will lose track of a resource if you change its name, move it to a different module, or change its provider. Usually that's fine: OpenTofu will destroy the old resource, replace it with a new one (using the new resource address), and update any resources that rely on its attributes. In cases where it's important to preserve an existing infrastructure object, you can explicitly tell OpenTofu to associate it with a different configured resource. For most cases we recommend using [the OpenTofu language's refactoring features](https://opentofu.org/docs/v1.11/language/modules/develop/refactoring/) to document in your module exactly how the resource names have changed over time. OpenTofu reacts to this information automatically during planning, so users of your module do not need to take any unusual extra steps. There are some other situations which require explicit state modifications, though. For those, consider the following OpenTofu commands: * [The `tofu state mv` command](https://opentofu.org/docs/v1.11/cli/commands/state/mv/) changes which resource address in your configuration is associated with a particular real-world object. Use this to preserve an object when renaming a resource, or when moving a resource into or out of a child module. * [The `tofu state rm` command](https://opentofu.org/docs/v1.11/cli/commands/state/rm/) tells OpenTofu to stop managing a resource as part of the current working directory and workspace, _without_ destroying the corresponding real-world object. (You can later use `tofu import` to start managing that resource in a different workspace or a different OpenTofu configuration.) * [The `tofu state replace-provider` command](https://opentofu.org/docs/v1.11/cli/commands/state/replace-provider/) transfers existing resources to a new provider without requiring them to be re-created. --- # Module Packages in OCI Registries | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/oci_registries/module-package/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Module Packages in OCI Registries ================================= OpenTofu supports installing module packages from [a variety of different sources](https://opentofu.org/docs/v1.11/language/modules/sources/) , including from repositories in registries that implement the OCI Distribution protocol. You can configure OpenTofu to install a module from an OCI repository by using the `oci:` source address scheme: Code Block module "example" { source = "oci://example.com/repository-name"} For more information on how to select OCI artifacts to install, refer to [the module sources documentation](https://opentofu.org/docs/v1.11/language/modules/sources/#oci-distribution-repository) . The remainder of this page focuses on how to construct suitable OCI artifacts for use as OpenTofu module packages. Required OCI Repository Content[​](https://opentofu.org/docs/v1.11/cli/oci_registries/module-package/#required-oci-repository-content "Direct link to Required OCI Repository Content") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The OCI artifact selected by an `oci:` module source address must follow certain requirements for both its manifest metadata and for the blob representing the content of the module package. The chosen tag or digest must correspond to a standard [OCI Image Manifest](https://github.com/opencontainers/image-spec/blob/v1.1.1/manifest.md) whose `artifactType` property is set to `"application/vnd.opentofu.modulepkg"`. The image manifest's `layers` array must include exactly one descriptor whose `mediaType` is `archive/zip`, referring to a valid `.zip` archive representing the content of the module package. The root directory of the `.zip` archive corresponds to the root directory of the module package, and so contains the `.tf`, `.tofu`, etc configuration files describing the default module from the module package. The archive may optionally contain subdirectories representing additional modules, which can then be selected using the usual syntax for [Modules in Package Sub-directories](https://opentofu.org/docs/v1.11/language/modules/sources/#modules-in-package-sub-directories) . If the specified source address does not include either of the `tag` or `digest` query string arguments then OpenTofu attempts to resolve a tag named `latest`. OpenTofu makes no other assumptions about tag naming convention beyond the syntax constraints required by the OCI Distribution specification. Assembling and Pushing Module Package Manifests[​](https://opentofu.org/docs/v1.11/cli/oci_registries/module-package/#assembling-and-pushing-module-package-manifests "Direct link to Assembling and Pushing Module Package Manifests") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### Install and Configure ORAS[​](https://opentofu.org/docs/v1.11/cli/oci_registries/module-package/#install-and-configure-oras "Direct link to Install and Configure ORAS") We recommend assembling and pushing the manifests and blobs for a module package using the CLI tool offered by [the ORAS project](https://oras.land/) . If you are installing and using ORAS for the first time, and you intend to push to an OCI registry that requires authentication, you will need to first obtain credentials for that repository using [`oras login`](https://oras.land/docs/commands/oras_login) . ### Create a `.zip` archive[​](https://opentofu.org/docs/v1.11/cli/oci_registries/module-package/#create-a-zip-archive "Direct link to create-a-zip-archive") The actual content of a module package is represented for an OCI artifact as a single layer using the `.zip` archive format. You can use any suitable tool to build a `.zip` archive containing the module source code (`.tf`/`.tofu`/etc files) you intend to distribute. For example, using the `zip` tool commonly available on Unix systems: Code Block zip -r ../module-package.zip . This command creates or updates an archive `module-package.zip` in the parent of the current working directory, containing all of the files in the current working directory and any of its subdirectories. Creating the file in the parent directory avoids adding the zip file into itself if you run the same command again. The next section will use `module-package.zip` to refer to the `.zip` archive you've created. ### Push the artifact to a remote repository[​](https://opentofu.org/docs/v1.11/cli/oci_registries/module-package/#push-the-artifact-to-a-remote-repository "Direct link to Push the artifact to a remote repository") The `oras push` command can automatically construct a suitable image manifest, upload that manifest and the associated `.zip` file to a remote OCI repository, and create or update one or more tags referring to it in the same repository. Code Block oras push \ --artifact-type=application/vnd.opentofu.modulepkg \ example.com/repository-name:latest \ module-package.zip:archive/zip `example.com/repository-name` is the address of the repository to push the artifact into. `latest` is the tag name to use. `module-package.zip` is the name of the `.zip` archive created in the previous step. The `:archive/zip` suffix tells ORAS which media type to specify for this file in the artifact manifest. OpenTofu does not support any other media types. The `--artifact-type` option included above must be used _exactly as shown_ to ensure that OpenTofu will recognize this artifact as a module package. The repository address and tag shown above can be specified in a `module` block source address as follows: Code Block module "example" { source = "oci://example.com/repository-name?tag=latest"} If you chose the tag name `latest` as shown here then you can omit the `tag` argument, specifying just `oci://example.com/repository-name`, because "latest" is the tag name OpenTofu uses by default. * [Required OCI Repository Content](https://opentofu.org/docs/v1.11/cli/oci_registries/module-package/#required-oci-repository-content) * [Assembling and Pushing Module Package Manifests](https://opentofu.org/docs/v1.11/cli/oci_registries/module-package/#assembling-and-pushing-module-package-manifests) * [Install and Configure ORAS](https://opentofu.org/docs/v1.11/cli/oci_registries/module-package/#install-and-configure-oras) * [Create a `.zip` archive](https://opentofu.org/docs/v1.11/cli/oci_registries/module-package/#create-a-zip-archive) * [Push the artifact to a remote repository](https://opentofu.org/docs/v1.11/cli/oci_registries/module-package/#push-the-artifact-to-a-remote-repository) --- # Installing OpenTofu | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/install/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Installing OpenTofu =================== You can install OpenTofu via a wide range of methods. Please select your operating system and installation method: [Alpine Linux (.apk)](https://opentofu.org/docs/v1.11/intro/install/alpine/) ----------------------------------------------------------------------------- Install OpenTofu from an .apk package directly. [Debian Linux and derivatives (.deb)](https://opentofu.org/docs/v1.11/intro/install/deb/) ------------------------------------------------------------------------------------------ Install OpenTofu on Debian, Ubuntu, or any other .deb-based Linux distribution using your package manager. [FreeBSD](https://opentofu.org/docs/v1.11/intro/install/bsd/) -------------------------------------------------------------- Use OpenTofu without installation on FreeBSD. [Fedora](https://opentofu.org/docs/v1.11/intro/install/fedora/) ---------------------------------------------------------------- Installing OpenTofu on Fedora. [RHEL and derivatives (.rpm)](https://opentofu.org/docs/v1.11/intro/install/rpm/) ---------------------------------------------------------------------------------- Install OpenTofu on RHEL, openSUSE, AlmaLinux, or any other .rpm-based Linux distribution using your package manager. [Ubuntu Linux (Snap)](https://opentofu.org/docs/v1.11/intro/install/snap/) --------------------------------------------------------------------------- Install OpenTofu on Ubuntu, Manjaro, or any other Linux distribution using Snap. [MacOS or Linux (Homebrew)](https://opentofu.org/docs/v1.11/intro/install/homebrew/) ------------------------------------------------------------------------------------- Install OpenTofu on MacOS or Linux using Homebrew. [Windows](https://opentofu.org/docs/v1.11/intro/install/windows/) ------------------------------------------------------------------ Install OpenTofu on Windows. [OCI container image](https://opentofu.org/docs/v1.11/intro/install/docker/) ----------------------------------------------------------------------------- Use official OCI container image available on GitHub Container Registry. [Standalone (Linux/MacOS/Windows/BSD)](https://opentofu.org/docs/v1.11/intro/install/standalone/) -------------------------------------------------------------------------------------------------- Use OpenTofu without installation on Linux, MacOS, Windows or FreeBSD. --- # Manipulating OpenTofu State | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/state/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Manipulating OpenTofu State =========================== OpenTofu uses [state data](https://opentofu.org/docs/v1.11/language/state/) to remember which real-world object corresponds to each resource in the configuration; this allows it to modify an existing object when its resource declaration changes. OpenTofu updates state automatically during plans and applies. However, it's sometimes necessary to make deliberate adjustments to OpenTofu's state data, usually to compensate for changes to the configuration or the real managed infrastructure. OpenTofu CLI supports several workflows for interacting with state: * [Inspecting State](https://opentofu.org/docs/v1.11/cli/state/inspect/) * [Forcing Re-creation](https://opentofu.org/docs/v1.11/cli/state/taint/) * [Moving Resources](https://opentofu.org/docs/v1.11/cli/state/move/) * Importing Pre-existing Resources (documented in the [Importing Infrastructure](https://opentofu.org/docs/v1.11/cli/import/) section) * [Disaster Recovery](https://opentofu.org/docs/v1.11/cli/state/recover/) Important Modifying state data outside a normal plan or apply can cause OpenTofu to lose track of managed resources, which might waste money, annoy your colleagues, or even compromise the security of your operations. Make sure to keep backups of your state data when modifying state out-of-band. --- # JSON Configuration Syntax | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/syntax/json/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page JSON Configuration Syntax ========================= Most OpenTofu configurations are written in [the native OpenTofu language syntax](https://opentofu.org/docs/v1.10/language/syntax/configuration/) , which is designed to be relatively easy for humans to read and update. OpenTofu also supports an alternative syntax that is JSON-compatible. This syntax is useful when generating portions of a configuration programmatically, since existing JSON libraries can be used to prepare the generated configuration files. The JSON syntax is defined in terms of the native syntax. Everything that can be expressed in native syntax can also be expressed in JSON syntax, but some constructs are more complex to represent in JSON due to limitations of the JSON grammar. OpenTofu expects native syntax for files named with a `.tf` or `.tofu` suffix, and JSON syntax for files named with a `.tf.json` or `.tofu.json` suffix. The low-level JSON syntax, just as with the native syntax, is defined in terms of a specification called _HCL_. It is not necessary to know all of the details of HCL syntax or its JSON mapping in order to use OpenTofu, and so this page summarizes the most important differences between native and JSON syntax. If you are interested, you can find a full definition of HCL's JSON syntax in [its specification](https://github.com/hashicorp/hcl/blob/main/json/spec.md) . ### Extension Precedence[​](https://opentofu.org/docs/v1.10/language/syntax/json/#extension-precedence "Direct link to Extension Precedence") When both `.tf.json` and `.tofu.json` files with the same base name are present in a directory, OpenTofu will prioritize the `.tofu.json` file and ignore the `.tf.json` file. For example: * If both `foo.tf.json` and `foo.tofu.json` exist in the same directory, OpenTofu will only load `foo.tofu.json` and ignore `foo.tf.json`. This ensures that `.tofu.json` files always take precedence over `.tf.json` files when both are available. This scenario can be useful for module authors who want their modules to support both OpenTofu and Terraform. JSON File Structure[​](https://opentofu.org/docs/v1.10/language/syntax/json/#json-file-structure "Direct link to JSON File Structure") --------------------------------------------------------------------------------------------------------------------------------------- At the root of any JSON-based OpenTofu configuration is a JSON object. The properties of this object correspond to the top-level block types of the OpenTofu language. For example: Code Block { "variable": { "example": { "default": "hello" } }} Each top-level object property must match the name of one of the expected top-level block types. Block types that expect labels, such as `variable` shown above, are represented by one nested object value for each level of label. `resource` blocks expect two labels, so two levels of nesting are required: Code Block { "resource": { "aws_instance": { "example": { "instance_type": "t2.micro", "ami": "ami-abc123" } } }} After any nested objects representing the labels, finally one more nested object represents the body of the block itself. In the above examples, the `default` argument for `variable "example"` and the `instance_type` and `ami` arguments for `resource "aws_instance" "example"` are specified. Taken together, the above two configuration files are equivalent to the following blocks in the native syntax: Code Block variable "example" { default = "hello"}resource "aws_instance" "example" { instance_type = "t2.micro" ami = "ami-abc123"} Within each top-level block type the rules for mapping to JSON are slightly different (see the [block-type-specific exceptions](https://opentofu.org/docs/v1.10/language/syntax/json/#block-type-specific-exceptions) below), but the following general rules apply in most cases: * The JSON object representing the block body contains properties that correspond either to argument names or to nested block type names. * Where a property corresponds to an argument that accepts [arbitrary expressions](https://opentofu.org/docs/v1.10/language/expressions/) in the native syntax, the property value is mapped to an expression as described under [_Expression Mapping_](https://opentofu.org/docs/v1.10/language/syntax/json/#expression-mapping) below. For arguments that do _not_ accept arbitrary expressions, the interpretation of the property value depends on the argument, as described in the [block-type-specific exceptions](https://opentofu.org/docs/v1.10/language/syntax/json/#block-type-specific-exceptions) given later in this page. * Where a property name corresponds to an expected nested block type name, the value is interpreted as described under [_Nested Block Mapping_](https://opentofu.org/docs/v1.10/language/syntax/json/#nested-block-mapping) below, unless otherwise stated in [the block-type-specific exceptions](https://opentofu.org/docs/v1.10/language/syntax/json/#block-type-specific-exceptions) given later in this page. Expression Mapping[​](https://opentofu.org/docs/v1.10/language/syntax/json/#expression-mapping "Direct link to Expression Mapping") ------------------------------------------------------------------------------------------------------------------------------------ Since JSON grammar is not able to represent all of the OpenTofu language [expression syntax](https://opentofu.org/docs/v1.10/language/expressions/) , JSON values interpreted as expressions are mapped as follows: | JSON | OpenTofu Language Interpretation | | --- | --- | | Boolean | A literal `bool` value. | | Number | A literal `number` value. | | String | Parsed as a [string template](https://opentofu.org/docs/v1.10/language/expressions/strings/#string-templates)
and then evaluated as described below. | | Object | Each property value is mapped per this table, producing an `object(...)` value with suitable attribute types. | | Array | Each element is mapped per this table, producing a `tuple(...)` value with suitable element types. | | Null | A literal `null`. | When a JSON string is encountered in a location where arbitrary expressions are expected, its value is first parsed as a \[string template\]\[\] and then it is evaluated to produce the final result. If the given template consists _only_ of a single interpolation sequence, the result of its expression is taken directly, without first converting it to a string. This allows non-string expressions to be used within the JSON syntax: Code Block { "output": { "example": { "value": "${aws_instance.example}" } }} The `output "example"` declared above has the object value representing the given `aws_instance` resource block as its value, rather than a string value. This special behavior does not apply if any literal or control sequences appear in the template; in these other situations, a string value is always produced. Nested Block Mapping[​](https://opentofu.org/docs/v1.10/language/syntax/json/#nested-block-mapping "Direct link to Nested Block Mapping") ------------------------------------------------------------------------------------------------------------------------------------------ When a JSON object property is named after a nested block type, the value of this property represents one or more blocks of that type. The value of the property must be either a JSON object or a JSON array. The simplest situation is representing only a single block of the given type when that type expects no labels, as with the `lifecycle` nested block used within `resource` blocks: Code Block { "resource": { "aws_instance": { "example": { "lifecycle": { "create_before_destroy": true } } } }} The above is equivalent to the following native syntax configuration: Code Block resource "aws_instance" "example" { lifecycle { create_before_destroy = true }} When the nested block type requires one or more labels, or when multiple blocks of the same type can be given, the mapping gets a little more complicated. For example, the `provisioner` nested block type used within `resource` blocks expects a label giving the provisioner to use, and the ordering of provisioner blocks is significant to decide the order of operations. The following native syntax example shows a `resource` block with a number of provisioners of different types: Code Block resource "aws_instance" "example" { # (resource configuration omitted for brevity) provisioner "local-exec" { command = "echo 'Hello World' >example.txt" } provisioner "file" { source = "example.txt" destination = "/tmp/example.txt" } provisioner "remote-exec" { inline = [ "sudo install-something -f /tmp/example.txt", ] }} In order to preserve the order of these blocks, you must use a JSON array as the direct value of the property representing this block type, as in this JSON equivalent of the above: Code Block { "resource": { "aws_instance": { "example": { "provisioner": [ { "local-exec": { "command": "echo 'Hello World' >example.txt" } }, { "file": { "source": "example.txt", "destination": "/tmp/example.txt" } }, { "remote-exec": { "inline": ["sudo install-something -f /tmp/example.txt"] } } ] } } }} Each element of the `provisioner` array is an object with a single property whose name represents the label for each `provisioner` block. For block types that expect multiple labels, this pattern of alternating array and object nesting can be used for each additional level. If a nested block type requires labels but the order does _not_ matter, you may omit the array and provide just a single object whose property names correspond to unique block labels. This is allowed as a shorthand for the above for simple cases, but the alternating array and object approach is the most general. We recommend using the most general form if systematically converting from native syntax to JSON, to ensure that the meaning of the configuration is preserved exactly. ### Comment Properties[​](https://opentofu.org/docs/v1.10/language/syntax/json/#comment-properties "Direct link to Comment Properties") Although we do not recommend hand-editing of JSON syntax configuration files -- this format is primarily intended for programmatic generation and consumption -- a limited form of _comments_ are allowed inside JSON objects that represent block bodies using a special property name: Code Block { "resource": { "aws_instance": { "example": { "//": "This instance runs the scheduled tasks for backup", "instance_type": "t2.micro", "ami": "ami-abc123" } } }} In any object that represents a block body, properties named `"//"` are ignored by OpenTofu entirely. This exception does _not_ apply to objects that are being [interpreted as expressions](https://opentofu.org/docs/v1.10/language/syntax/json/#expression-mapping) , where this would be interpreted as an object type attribute named `"//"`. This special property name can also be used at the root of a JSON-based configuration file. This can be useful to note which program created the file. Code Block { "//": "This file is generated by generate-outputs.py. DO NOT HAND-EDIT!", "output": { "example": { "value": "${aws_instance.example}" } }} Block-type-specific Exceptions[​](https://opentofu.org/docs/v1.10/language/syntax/json/#block-type-specific-exceptions "Direct link to Block-type-specific Exceptions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Certain arguments within specific block types are processed in a special way by OpenTofu, and so their mapping to the JSON syntax does not follow the general rules described above. The following sub-sections describe the special mapping rules that apply to each top-level block type. ### `resource` and `data` blocks[​](https://opentofu.org/docs/v1.10/language/syntax/json/#resource-and-data-blocks "Direct link to resource-and-data-blocks") Some meta-arguments for the `resource` and `data` block types take direct references to objects, or literal keywords. When represented in JSON, the reference or keyword is given as a JSON string with no additional surrounding spaces or symbols. For example, the `provider` meta-argument takes a `.` reference to a provider configuration, which appears unquoted in the native syntax but must be presented as a string in the JSON syntax: Code Block { "resource": { "aws_instance": { "example": { "provider": "aws.foo" } } }} This special processing applies to the following meta-arguments: * `provider`: a single string, as shown above * `depends_on`: an array of strings containing references to named entities, like `["aws_instance.example"]`. * `ignore_changes` within the `lifecycle` block: if set to `all`, a single string `"all"` must be given. Otherwise, an array of JSON strings containing property references must be used, like `["ami"]`. Special processing also applies to the `type` argument of any `connection` blocks, whether directly inside the `resource` block or nested inside `provisioner` blocks: the given string is interpreted literally, and not parsed and evaluated as a string template. ### `variable` blocks[​](https://opentofu.org/docs/v1.10/language/syntax/json/#variable-blocks "Direct link to variable-blocks") All arguments inside `variable` blocks have non-standard mappings to JSON: * `type`: a string containing a type expression, like `"string"` or `"list(string)"`. * `default`: a literal JSON value that can be converted to the given type. Strings within this value are taken literally and _not_ interpreted as string templates. * `description`: a literal JSON string, _not_ interpreted as a template. Code Block { "variable": { "example": { "type": "string", "default": "hello" } }} ### `output` blocks[​](https://opentofu.org/docs/v1.10/language/syntax/json/#output-blocks "Direct link to output-blocks") The `description` and `sensitive` arguments are interpreted as literal JSON values. The `description` string is not interpreted as a string template. The `value` argument is [interpreted as an expression](https://opentofu.org/docs/v1.10/language/syntax/json/#expression-mapping) . Code Block { "output": { "example": { "value": "${aws_instance.example}" } }} ### `locals` blocks[​](https://opentofu.org/docs/v1.10/language/syntax/json/#locals-blocks "Direct link to locals-blocks") The value of the JSON object property representing the locals block type must be a JSON object whose property names are the local value names to declare: Code Block { "locals": { "greeting": "Hello, ${var.name}" }} The value of each of these nested properties is [interpreted as an expression](https://opentofu.org/docs/v1.10/language/syntax/json/#expression-mapping) . ### `module` blocks[​](https://opentofu.org/docs/v1.10/language/syntax/json/#module-blocks "Direct link to module-blocks") The `providers` meta-argument must be given as a JSON object whose properties are the compact provider addresses to expose into the child module and whose values are the provider addresses to use from the current module, both given as literal strings: Code Block { "module": { "example": { "source": "hashicorp/consul/azurerm", "version": "= 1.0.0", "providers": { "aws": "aws.usw1" } } }} ### `provider` blocks[​](https://opentofu.org/docs/v1.10/language/syntax/json/#provider-blocks "Direct link to provider-blocks") The `alias` and `version` meta-arguments must be given as literal strings. The values are not interpreted as string templates. Code Block { "provider": { "aws": [ { "region": "us-east-1" }, { "alias": "usw1", "region": "us-west-1" } ] }} ### `terraform` blocks[​](https://opentofu.org/docs/v1.10/language/syntax/json/#terraform-blocks "Direct link to terraform-blocks") Settings within `terraform` blocks are generally interpreted literally, except for the `backend` block, which supports expressions. Other settings do not accept named object references or function calls and therefore do not treat string values as string templates. Since only one `backend` block is allowed per `terraform` block, the compact block mapping can be used to represent it, with a nested object containing a single property whose name represents the backend type. Code Block { "terraform": { "required_version": ">= 0.12.0", "backend": { "s3": { "region": "us-west-2", "bucket": "acme-tofu-states" } } }} * [Extension Precedence](https://opentofu.org/docs/v1.10/language/syntax/json/#extension-precedence) * [JSON File Structure](https://opentofu.org/docs/v1.10/language/syntax/json/#json-file-structure) * [Expression Mapping](https://opentofu.org/docs/v1.10/language/syntax/json/#expression-mapping) * [Nested Block Mapping](https://opentofu.org/docs/v1.10/language/syntax/json/#nested-block-mapping) * [Comment Properties](https://opentofu.org/docs/v1.10/language/syntax/json/#comment-properties) * [Block-type-specific Exceptions](https://opentofu.org/docs/v1.10/language/syntax/json/#block-type-specific-exceptions) * [`resource` and `data` blocks](https://opentofu.org/docs/v1.10/language/syntax/json/#resource-and-data-blocks) * [`variable` blocks](https://opentofu.org/docs/v1.10/language/syntax/json/#variable-blocks) * [`output` blocks](https://opentofu.org/docs/v1.10/language/syntax/json/#output-blocks) * [`locals` blocks](https://opentofu.org/docs/v1.10/language/syntax/json/#locals-blocks) * [`module` blocks](https://opentofu.org/docs/v1.10/language/syntax/json/#module-blocks) * [`provider` blocks](https://opentofu.org/docs/v1.10/language/syntax/json/#provider-blocks) * [`terraform` blocks](https://opentofu.org/docs/v1.10/language/syntax/json/#terraform-blocks) --- # OCI Registry Credentials | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page OCI Registry Credentials ======================== All of the OpenTofu features which interact with OCI Registries use a centralized mechanism for obtaining credentials to use when making requests. Default Implicit Behavior[​](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/#default-implicit-behavior "Direct link to Default Implicit Behavior") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- By default, OpenTofu searches the following locations for "Docker-style" configuration files containing credentials, likely to have been issued by other software that interacts with OCI registries: * `$XDG_RUNTIME_DIR/containers/auth.json` (Linux only) * `$HOME/.config/containers/auth.json` (Windows and macOS only) * `$XDG_CONFIG_HOME/containers/auth.json` (`XDG_CONFIG_HOME` defaults to `$HOME/.config`) * `$HOME/.docker/config.json` * `$HOME/.dockercfg` In these files, OpenTofu expects to find configuration following the format specified in [`containers-auth.json`](https://github.com/containers/image/blob/22415d4f7ea9cd9ffbfc46bcf919137dabf0c3bb/docs/containers-auth.json.5.md) . Although you can hand-write these configuration files, the more common way to populate them is to run the "login" command of some other OCI-integrated software, such as `docker login`, `oras login`, `buildah login`, `skopeo login`, etc. All of those commands write the resulting credentials into one of the file paths listed above. OpenTofu selects the credentials associated with the pattern that most specifically matches the target repository address. For example, when making a request to a repository at `example.com/foo/bar`, OpenTofu prefers to use credentials configured for `example.com/foo` over credentials configured just for `example.com`. When there are multiple matching credentials of equal precedence, files earlier in the list above take priority over files later in the list. You can customize some aspects of this implicit credentials discovery behavior as part of [Default Credentials Configuration](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/#default-credentials-configuration) . Explicit Credentials Configuration[​](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/#explicit-credentials-configuration "Direct link to Explicit Credentials Configuration") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu also allows direct configuration of OCI Registry credentials as part of [the CLI configuration file](https://opentofu.org/docs/v1.11/cli/config/config-file/) , using `oci_credentials` blocks: Code Block oci_credentials "example.com" { username = "example" password = "example"} The label of each `oci_credentials` block must be an OCI registry domain name followed by an optional repository path prefix. For example, `example.com` matches all repositories on that registry, while `example.com/foo` only matches repositories whose name starts with a "foo" path segment. The content of an `oci_credentials` block has three forms depending on the kind of credentials and how they are specified: * **Inline username and password:** Use `username` and `password` arguments to directly specify credentials to use for authentication schemes like HTTP "Basic" authentication. When you specify a password directly you must protect your CLI Configuration file to avoid your secret password becoming compromised. * **Docker-style credential helper:** Use the `docker_credentials_helper` argument to specify the name of a program implementing the [Docker Credential Helper](https://github.com/docker/docker-credential-helpers) protocol, which OpenTofu then launches to obtain credentials only when they are needed. For example, if you work on macOS and install the `osxkeychain` credential helper then you can specify `docker_credentials_helper = "osxkeychain"` to make OpenTofu obtain credentials from your macOS Keychain. OpenTofu currently uses credential helpers only on a read-only basis, so any needed credentials must first be written into the underlying credential store using other software that has been configured to write credentials through the same credential helper. * **Inline OAuth credentials:** Use `access_token` and `refresh_token` arguments to directly specify OAuth-style credentials. When you specify an access token and refresh token directly you must protect your CLI Configuration file to avoid your tokens becoming compromised. When multiple `oci_credentials` blocks are present, OpenTofu selects the one whose block label most closely matches the target repository. By default, OpenTofu uses explicit `oci_credentials` blocks in conjunction with any automatically-discovered Docker-style configuration files, taking the most specific match across all of these sources. If the same repository address prefix is specified both in an explicit `oci_credentials` block and in a Docker-style configuration file then the explicit configuration takes priority. Default Credentials Configuration[​](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/#default-credentials-configuration "Direct link to Default Credentials Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The optional `oci_default_credentials` block type can appear at most once in the CLI configuration. When present, it customizes the [default implicit search behavior](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/#default-implicit-behavior) , or disables it entirely. The following arguments may appear in an `oci_default_credentials` block: * `discover_ambient_credentials`: Set this to `false` to completely disable all of the implicit search behavior, in which case only [explicit credentials configuration](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/#explicit-credentials-configuration) can be used. Defaults to `true`, which allows the implicit search behavior. * `docker_style_config_files`: A list of strings specifying filenames to treat as Docker-style configuration files, instead of the default search locations. Set `docker_style_config_files = []` to prevent searching for any Docker-style configuration files while still allowing discovery of other "ambient" credentials. Docker-style configuration files are currently the only available ambient credentials mechanism and so this is equivalent to `discover_ambient_credentials = false`, but that might change in future versions of OpenTofu. * `docker_credentials_helper`: Directly specifies the name of a global Docker-style credentials helper to use for all OCI repositories that are not matched by a more specific credentials configuration. For example, specify `docker_credentials_helper = "osxkeychain"` to make OpenTofu obtain credentials from your macOS Keychain. You must install the selected credential helper first so that OpenTofu can execute it. Note **OpenTofu does not use any credential helper unless explicitly configured to do so.** Docker CLI and some other more-closely-related software default to searching certain hard-coded credential helper names depending on your platform when no credential helper is configured and no static credentials are available. To avoid executing third-party software without explicit consent, OpenTofu instead requires that you directly configure any credential helper you intend to use, either by using this OpenTofu-specific setting or by using [the `"credsStore"` property](https://docs.docker.com/reference/cli/docker/#credential-store-options) in your Docker CLI configuration file. * [Default Implicit Behavior](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/#default-implicit-behavior) * [Explicit Credentials Configuration](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/#explicit-credentials-configuration) * [Default Credentials Configuration](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/#default-credentials-configuration) --- # Installing OpenTofu on Alpine Linux | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/install/alpine/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Installing OpenTofu on Alpine Linux =================================== OpenTofu is available in the [Alpine Linux testing repository](https://pkgs.alpinelinux.org/packages?name=opentofu) or as an `.apk` package from the [GitHub releases page](https://github.com/opentofu/opentofu/releases/latest/) . Installing using the installer[​](https://opentofu.org/docs/v1.11/intro/install/alpine/#installing-using-the-installer "Direct link to Installing using the installer") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ You can use the OpenTofu installer script to run the installation. Code Block # Download the installer script:curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh -o install-opentofu.sh# Alternatively: wget --secure-protocol=TLSv1_2 --https-only https://get.opentofu.org/install-opentofu.sh -O install-opentofu.sh# Give it execution permissions:chmod +x install-opentofu.sh# Please inspect the downloaded script# Run the installer:./install-opentofu.sh --install-method apk# Remove the installer:rm -f install-opentofu.sh Installing the .apk[​](https://opentofu.org/docs/v1.11/intro/install/alpine/#installing-the-apk "Direct link to Installing the .apk") -------------------------------------------------------------------------------------------------------------------------------------- You can also [download the .apk](https://github.com/opentofu/opentofu/releases/latest/) and install it on your Alpine Linux. You can install the `.apk` package after downloading it: Code Block apk add --allow-untrusted tofu_*.apk Installing from the testing repository[​](https://opentofu.org/docs/v1.11/intro/install/alpine/#installing-from-the-testing-repository "Direct link to Installing from the testing repository") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ OpenTofu is currently available in the Alpine Testing repository and coming to Alpine stable. You can use the following commands to test Alpine installation. Code Block echo '@community https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositoriesapk add opentofu@community * [Installing using the installer](https://opentofu.org/docs/v1.11/intro/install/alpine/#installing-using-the-installer) * [Installing the .apk](https://opentofu.org/docs/v1.11/intro/install/alpine/#installing-the-apk) * [Installing from the testing repository](https://opentofu.org/docs/v1.11/intro/install/alpine/#installing-from-the-testing-repository) --- # Installing OpenTofu on FreeBSD | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/install/bsd/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Installing OpenTofu on FreeBSD ============================== OpenTofu is available for FreeBSD and can be installed using the [pkg](https://pkgs.org/download/opentofu) and [port](https://cgit.freebsd.org/ports/commit/?id=f49b835b51fd5d92138706c32523c6f361740eac) system or by downloading the package directly. Installing using the pkg[​](https://opentofu.org/docs/v1.11/intro/install/bsd/#installing-using-the-pkg "Direct link to Installing using the pkg") --------------------------------------------------------------------------------------------------------------------------------------------------- Code Block pkg update -fpkg install opentofu Installing the port[​](https://opentofu.org/docs/v1.11/intro/install/bsd/#installing-the-port "Direct link to Installing the port") ------------------------------------------------------------------------------------------------------------------------------------ Code Block portsnap fetch extractmake -C /usr/ports/sysutils/opentofu install clean * [Installing using the pkg](https://opentofu.org/docs/v1.11/intro/install/bsd/#installing-using-the-pkg) * [Installing the port](https://opentofu.org/docs/v1.11/intro/install/bsd/#installing-the-port) --- # Installing OpenTofu on Fedora | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/install/fedora/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Installing OpenTofu on Fedora ============================= OpenTofu is available in the [Fedora repository](https://src.fedoraproject.org/rpms/opentofu) as an `.rpm` package. Installing the .rpm package[​](https://opentofu.org/docs/v1.11/intro/install/fedora/#installing-the-rpm-package "Direct link to Installing the .rpm package") -------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block dnf install opentofu * [Installing the .rpm package](https://opentofu.org/docs/v1.11/intro/install/fedora/#installing-the-rpm-package) --- # Installing OpenTofu via Homebrew | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/install/homebrew/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Installing OpenTofu via Homebrew ================================ You can use OpenTofu as a [standalone binary](https://opentofu.org/docs/v1.11/intro/install/standalone/) or you can install it using [Homebrew](https://formulae.brew.sh/formula/opentofu) . OpenTofu is available in the Homebrew Core repository, so you can install it by running: Code Block brew updatebrew install opentofu Validate the installation by running: Code Block tofu -version --- # Installing OpenTofu via Snapcraft (Linux) | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/install/snap/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Installing OpenTofu via Snapcraft (Linux) ========================================= OpenTofu is available on [Snapcraft](https://snapcraft.io/) and you can install it by running: Code Block snap install --classic opentofu Snap is available by default on Ubuntu Linux and [can be installed on other Linux distributions, too](https://snapcraft.io/docs/installing-snapd) . --- # Output Values | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/values/outputs/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Output Values ============= Output values make information about your infrastructure available on the command line, and can expose information for other OpenTofu configurations to use. Output values are similar to return values in programming languages. Output values have several uses: * A child module can use outputs to expose a subset of its resource attributes to a parent module. * A root module can use outputs to print certain values in the CLI output after running `tofu apply`. * When using [remote state](https://opentofu.org/docs/v1.10/language/state/remote/) , root module outputs can be accessed by other configurations via a [`terraform_remote_state` data source](https://opentofu.org/docs/v1.10/language/state/remote-state-data/) . Resource instances managed by OpenTofu each export attributes whose values can be used elsewhere in configuration. Output values are a way to expose some of that information to the user of your module. Note For brevity, output values are often referred to as just "outputs" when the meaning is clear from context. Declaring an Output Value[​](https://opentofu.org/docs/v1.10/language/values/outputs/#declaring-an-output-value "Direct link to Declaring an Output Value") ------------------------------------------------------------------------------------------------------------------------------------------------------------ Each output value exported by a module must be declared using an `output` block: Code Block output "instance_ip_addr" { value = aws_instance.server.private_ip} The label immediately after the `output` keyword is the name, which must be a valid [identifier](https://opentofu.org/docs/v1.10/language/syntax/configuration/#identifiers) . In a root module, this name is displayed to the user; in a child module, it can be used to access the output's value. The `value` argument takes an [expression](https://opentofu.org/docs/v1.10/language/expressions/) whose result is to be returned to the user. In this example, the expression refers to the `private_ip` attribute exposed by an `aws_instance` resource defined elsewhere in this module (not shown). Any valid expression is allowed as an output value. Note Outputs are only rendered when OpenTofu applies your plan. Running `tofu plan` will not render outputs. Accessing Child Module Outputs[​](https://opentofu.org/docs/v1.10/language/values/outputs/#accessing-child-module-outputs "Direct link to Accessing Child Module Outputs") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- In a parent module, outputs of child modules are available in expressions as `module..`. For example, if a child module named `web_server` declared an output named `instance_ip_addr`, you could access that value as `module.web_server.instance_ip_addr`. Custom Condition Checks[​](https://opentofu.org/docs/v1.10/language/values/outputs/#custom-condition-checks "Direct link to Custom Condition Checks") ------------------------------------------------------------------------------------------------------------------------------------------------------ You can use `precondition` blocks to specify guarantees about output data. The following examples creates a precondition that checks whether the EC2 instance has an encrypted root volume. Code Block output "api_base_url" { value = "https://${aws_instance.example.private_dns}:8433/" # The EC2 instance must have an encrypted root volume. precondition { condition = data.aws_ebs_volume.example.encrypted error_message = "The server's root volume is not encrypted." }} Custom conditions can help capture assumptions, helping future maintainers understand the configuration design and intent. They also return useful information about errors earlier and in context, helping consumers more easily diagnose issues in their configurations. Refer to [Custom Condition Checks](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#preconditions-and-postconditions) for more details. Optional Arguments[​](https://opentofu.org/docs/v1.10/language/values/outputs/#optional-arguments "Direct link to Optional Arguments") --------------------------------------------------------------------------------------------------------------------------------------- `output` blocks can optionally include `description`, `sensitive`, and `depends_on` arguments, which are described in the following sections. ### `description` β€” Output Value Documentation[​](https://opentofu.org/docs/v1.10/language/values/outputs/#description--output-value-documentation "Direct link to description--output-value-documentation") Because the output values of a module are part of its user interface, you can briefly describe the purpose of each value using the optional `description` argument: Code Block output "instance_ip_addr" { value = aws_instance.server.private_ip description = "The private IP address of the main server instance."} The description should concisely explain the purpose of the output and what kind of value is expected. This description string might be included in documentation about the module, and so it should be written from the perspective of the user of the module rather than its maintainer. For commentary for module maintainers, use comments. ### `sensitive` β€” Suppressing Values in CLI Output[​](https://opentofu.org/docs/v1.10/language/values/outputs/#sensitive--suppressing-values-in-cli-output "Direct link to sensitive--suppressing-values-in-cli-output") An output can be marked as containing sensitive material using the optional `sensitive` argument: Code Block output "db_password" { value = aws_db_instance.db.password description = "The password for logging in to the database." sensitive = true} OpenTofu will hide values marked as sensitive in the messages from `tofu plan` and `tofu apply`. In the following scenario, our root module has an output declared as sensitive and a module call with a sensitive output, which we then use in a resource attribute. Code Block # main.tfmodule "foo" { source = "./mod"}resource "test_instance" "x" { some_attribute = module.foo.a # resource attribute references a sensitive output}output "out" { value = "xyz" sensitive = true}# mod/main.tf, our module containing a sensitive outputoutput "a" { value = "secret" sensitive = true} When we run a plan or apply, the sensitive value is redacted from output: Code Block OpenTofu will perform the following actions: # test_instance.x will be created + resource "test_instance" "x" { + some_attribute = (sensitive value) }Plan: 1 to add, 0 to change, 0 to destroy.Changes to Outputs: + out = (sensitive value) OpenTofu will still record sensitive values in the [state](https://opentofu.org/docs/v1.10/language/state/) , and so anyone who can access the state data will have access to the sensitive values in cleartext. For more information, see [_Sensitive Data in State_](https://opentofu.org/docs/v1.10/language/state/sensitive-data/) . ### `depends_on` β€” Explicit Output Dependencies[​](https://opentofu.org/docs/v1.10/language/values/outputs/#depends_on--explicit-output-dependencies "Direct link to depends_on--explicit-output-dependencies") Since output values are just a means for passing data out of a module, it is usually not necessary to worry about their relationships with other nodes in the dependency graph. However, when a parent module accesses an output value exported by one of its child modules, the dependencies of that output value allow OpenTofu to correctly determine the dependencies between resources defined in different modules. Just as with [resource dependencies](https://opentofu.org/docs/v1.10/language/resources/behavior/#resource-dependencies) , OpenTofu analyzes the `value` expression for an output value and automatically determines a set of dependencies, but in less-common cases there are dependencies that cannot be recognized implicitly. In these rare cases, the `depends_on` argument can be used to create additional explicit dependencies: Code Block output "instance_ip_addr" { value = aws_instance.server.private_ip description = "The private IP address of the main server instance." depends_on = [ # Security group rule must be created before this IP address could # actually be used, otherwise the services will be unreachable. aws_security_group_rule.local_access, ]} The `depends_on` argument should be used only as a last resort. When using it, always include a comment explaining why it is being used, to help future maintainers understand the purpose of the additional dependency. ### `deprecated` β€” Marking output as deprecated[​](https://opentofu.org/docs/v1.10/language/values/outputs/#deprecated--marking-output-as-deprecated "Direct link to deprecated--marking-output-as-deprecated") Warning This feature is considered experimental and the final UX may change in the future. The `deprecated` argument in a module output block indicates its deprecation and potential removal in the future. This attribute should contain non-empty string and should provide instructions on how to migrate away from usage of this module output. Here is an example of the configuration: Code Block output "examle" { value = "someval" deprecated = "'examle' output must no longer be used due to a typo, use 'example' instead"} The caller of the module will receive a warning if the deprecated output is referenced in their configuration: Code Block β•·β”‚ Warning: Value derived from a deprecated sourceβ”‚ β”‚ on main.tf line 45, in locals:β”‚ 45: a = module.mod.examleβ”‚ β”‚ This value is derived from module.mod.examle, which is deprecated with the following message:β”‚ β”‚ 'examle' output must no longer be used due to a typo, use 'example' instead Deprecation warnings can be filtered or disabled by using the `-deprecation` CLI argument. For more details, check its description in the command options for [plan](https://opentofu.org/docs/v1.10/cli/commands/plan/#other-options) and [apply](https://opentofu.org/docs/v1.10/cli/commands/apply/#apply-options) . * [Declaring an Output Value](https://opentofu.org/docs/v1.10/language/values/outputs/#declaring-an-output-value) * [Accessing Child Module Outputs](https://opentofu.org/docs/v1.10/language/values/outputs/#accessing-child-module-outputs) * [Custom Condition Checks](https://opentofu.org/docs/v1.10/language/values/outputs/#custom-condition-checks) * [Optional Arguments](https://opentofu.org/docs/v1.10/language/values/outputs/#optional-arguments) * [`description` β€” Output Value Documentation](https://opentofu.org/docs/v1.10/language/values/outputs/#description--output-value-documentation) * [`sensitive` β€” Suppressing Values in CLI Output](https://opentofu.org/docs/v1.10/language/values/outputs/#sensitive--suppressing-values-in-cli-output) * [`depends_on` β€” Explicit Output Dependencies](https://opentofu.org/docs/v1.10/language/values/outputs/#depends_on--explicit-output-dependencies) * [`deprecated` β€” Marking output as deprecated](https://opentofu.org/docs/v1.10/language/values/outputs/#deprecated--marking-output-as-deprecated) --- # Managing Plugins | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/plugins/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Managing Plugins ================ OpenTofu relies on plugins called "providers" in order to manage various types of resources. (For more information about providers, see [Providers](https://opentofu.org/docs/v1.11/language/providers/) in the OpenTofu language docs.) Note Providers are the only plugin type most OpenTofu users interact with. OpenTofu also supports third-party provisioner plugins, but we discourage their use. OpenTofu downloads and/or installs any providers [required](https://opentofu.org/docs/v1.11/language/providers/requirements/) by a configuration when [initializing](https://opentofu.org/docs/v1.11/cli/init/) a working directory. By default, this works without any additional interaction but requires network access to download providers from their source registry. You can configure OpenTofu's provider installation behavior to limit or skip network access, and to enable use of providers that aren't available via a networked source. OpenTofu also includes some commands to show information about providers and to reduce the effort of installing providers in airgapped environments. Configuring Plugin Installation[​](https://opentofu.org/docs/v1.11/cli/plugins/#configuring-plugin-installation "Direct link to Configuring Plugin Installation") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ OpenTofu's configuration file includes options for caching downloaded plugins, or explicitly specifying a local or HTTPS mirror to install plugins from. For more information, see [CLI Config File](https://opentofu.org/docs/v1.11/cli/config/config-file/) . Getting Plugin Information[​](https://opentofu.org/docs/v1.11/cli/plugins/#getting-plugin-information "Direct link to Getting Plugin Information") --------------------------------------------------------------------------------------------------------------------------------------------------- Use the [`tofu providers`](https://opentofu.org/docs/v1.11/cli/commands/providers/) command to get information about the providers required by the current working directory's configuration. Use the [`tofu version`](https://opentofu.org/docs/v1.11/cli/commands/version/) command (or `tofu -version`) to show the specific provider versions installed for the current working directory. Use the [`tofu providers schema`](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/) command to get machine-readable information about the resources and configuration options offered by each provider. Managing Plugin Installation[​](https://opentofu.org/docs/v1.11/cli/plugins/#managing-plugin-installation "Direct link to Managing Plugin Installation") --------------------------------------------------------------------------------------------------------------------------------------------------------- Use the [`tofu providers mirror`](https://opentofu.org/docs/v1.11/cli/commands/providers/mirror/) command to download local copies of every provider required by the current working directory's configuration. This directory will use the nested directory layout that OpenTofu expects when installing plugins from a local source, so you can transfer it directly to an airgapped system that runs OpenTofu. Use the [`tofu providers lock`](https://opentofu.org/docs/v1.11/cli/commands/providers/lock/) command to update the lock file that OpenTofu uses to ensure predictable runs when using ambiguous provider version constraints. * [Configuring Plugin Installation](https://opentofu.org/docs/v1.11/cli/plugins/#configuring-plugin-installation) * [Getting Plugin Information](https://opentofu.org/docs/v1.11/cli/plugins/#getting-plugin-information) * [Managing Plugin Installation](https://opentofu.org/docs/v1.11/cli/plugins/#managing-plugin-installation) --- # Forcing Re-creation of Resources | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/state/taint/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Forcing Re-creation of Resources ================================ During planning, by default OpenTofu retrieves the latest state of each existing object and compares it with the current configuration, planning actions only against objects whose current state does not match the configuration. However, in some cases a remote object may become damaged or degraded in a way that OpenTofu cannot automatically detect. For example, if software running inside a virtual machine crashes but the virtual machine itself is still running then OpenTofu will typically have no way to detect and respond to the problem, because OpenTofu only directly manages the machine as a whole. If you know that an object is damaged, or if you want to force OpenTofu to replace it for any other reason, you can override OpenTofu's default behavior using [the `-replace=...` planning option](https://opentofu.org/docs/v1.11/cli/commands/plan/#replace-address) when you run either `tofu plan` or `tofu apply`: Code Block $ tofu apply -replace="aws_instance.example"# ... # aws_instance.example will be replaced, as requested-/+ resource "aws_instance" "example" { # ... } The "tainted" status[​](https://opentofu.org/docs/v1.11/cli/state/taint/#the-tainted-status "Direct link to The "tainted" status") ----------------------------------------------------------------------------------------------------------------------------------- Sometimes OpenTofu is able to infer automatically that an object is in an incomplete or degraded state. For example, if creation of a complex object fails in such a way that parts of it already exist in the remote system, or if object creation succeeded but a provisioner step subsequently failed, OpenTofu must remember that the object exists but may not be fully-functional. OpenTofu represents this situation by marking an object in the state as "tainted". When an object is marked with this status, the next plan will force replacing that object in a similar way to if you had specified that object's address using `-replace=...` as described above. Code Block # aws_instance.example is tainted, so it must be replaced-/+ resource "aws_instance" "example" { # ... } If OpenTofu has marked an object as tainted but you consider it to be working correctly and do not want to replace it, you can override OpenTofu's determination using [the `tofu untaint` command](https://opentofu.org/docs/v1.11/cli/commands/untaint/) , after which OpenTofu will consider the object to be ready for use by any downstream resource declarations. You can also _force_ OpenTofu to mark a particular object as tainted using [the `tofu taint` command](https://opentofu.org/docs/v1.11/cli/commands/taint/) , but that approach is deprecated in favor of the `-replace=...` option, which avoids the need to create an interim state snapshot with a tainted object. * [The "tainted" status](https://opentofu.org/docs/v1.11/cli/state/taint/#the-tainted-status) --- # Installing OpenTofu from GitHub Releases | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/install/windows/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Installing OpenTofu from GitHub Releases ======================================== * winget * scoop OpenTofu is available on [the winget repository](https://github.com/microsoft/winget-pkgs/tree/master/manifests/o/OpenTofu/Tofu/) and you can install it by running: Code Block winget install --exact --id=OpenTofu.Tofu Verify installation: Code Block tofu -version Note If you run into issues when installing with winget, please make sure that `%LOCALAPPDATA%\Microsoft\WinGet\Links` is in your PATH environment variable. OpenTofu is available on [the scoop repository](https://github.com/ScoopInstaller/Main/blob/master/bucket/opentofu.json) and you can install it by running: Code Block scoop bucket add mainscoop install main/opentofu Verify installation: Code Block tofu -version --- # Environment Variables | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Environment Variables ===================== OpenTofu refers to a number of environment variables to customize various aspects of its behavior. None of these environment variables are required when using OpenTofu, but they can be used to change some of OpenTofu's default behaviors in unusual situations, or to increase output verbosity for debugging. TF\_LOG[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_log "Direct link to TF_LOG") ------------------------------------------------------------------------------------------------------------- Enables detailed logs to appear on stderr which is useful for debugging. For example: Code Block export TF_LOG=trace To disable, either unset it, or set it to `off`. For example: Code Block export TF_LOG=off For more on debugging OpenTofu, check out the section on [Debugging](https://opentofu.org/docs/v1.11/internals/debugging/) . TF\_LOG\_PATH[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_log_path "Direct link to TF_LOG_PATH") ----------------------------------------------------------------------------------------------------------------------------- This specifies where the log should persist its output to. Note that even when `TF_LOG_PATH` is set, `TF_LOG` must be set in order for any logging to be enabled. For example, to always write the log to the directory you're currently running tofu from: Code Block export TF_LOG_PATH=./terraform.log For more on debugging OpenTofu, check out the section on [Debugging](https://opentofu.org/docs/v1.11/internals/debugging/) . TF\_INPUT[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_input "Direct link to TF_INPUT") ------------------------------------------------------------------------------------------------------------------- If set to "false" or "0", causes tofu commands to behave as if the `-input=false` flag was specified. This is used when you want to disable prompts for variables that haven't had their values specified. For example: Code Block export TF_INPUT=0 TF\_VAR\_name[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_var_name "Direct link to TF_VAR_name") ----------------------------------------------------------------------------------------------------------------------------- Environment variables can be used to set variables. The environment variables must be in the format `TF_VAR_name` and this will be checked last for a value. For example: Code Block export TF_VAR_region=us-west-1export TF_VAR_ami=ami-049d8641export TF_VAR_alist='[1,2,3]'export TF_VAR_amap='{ foo = "bar", baz = "qux" }' For more on how to use `TF_VAR_name` in context, check out the section on [Variable Configuration](https://opentofu.org/docs/v1.11/language/values/variables/) . TF\_CLI\_ARGS and TF\_CLI\_ARGS\_name[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_cli_args-and-tf_cli_args_name "Direct link to TF_CLI_ARGS and TF_CLI_ARGS_name") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The value of `TF_CLI_ARGS` will specify additional arguments to the command-line. This allows easier automation in CI environments as well as modifying default behavior of OpenTofu on your own system. These arguments are inserted directly _after_ the subcommand (such as `plan`) and _before_ any flags specified directly on the command-line. This behavior ensures that flags on the command-line take precedence over environment variables. For example, the following command: `TF_CLI_ARGS="-input=false" tofu apply -force` is the equivalent to manually typing: `tofu apply -input=false -force`. The flag `TF_CLI_ARGS` affects all OpenTofu commands. If you specify a named command in the form of `TF_CLI_ARGS_name` then it will only affect that command. As an example, to specify that only plans never refresh, you can set `TF_CLI_ARGS_plan="-refresh=false"`. The value of the flag is parsed as if you typed it directly to the shell. Double and single quotes are allowed to capture strings and arguments will be separated by spaces otherwise. TF\_DATA\_DIR[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_data_dir "Direct link to TF_DATA_DIR") ----------------------------------------------------------------------------------------------------------------------------- `TF_DATA_DIR` changes the location where OpenTofu keeps its per-working-directory data, such as the current backend configuration. By default this data is written into a `.terraform` subdirectory of the current directory, but the path given in `TF_DATA_DIR` will be used instead if non-empty. In most cases it should not be necessary to set this variable, but it may be useful to do so if e.g. the working directory is not writable. The data directory is used to retain data that must persist from one command to the next, so it's important to have this variable set consistently throughout all of the OpenTofu workflow commands (starting with `tofu init`) or else OpenTofu may be unable to find providers, modules, and other artifacts. TF\_WORKSPACE[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_workspace "Direct link to TF_WORKSPACE") ------------------------------------------------------------------------------------------------------------------------------- For multi-environment deployment, in order to select a workspace, instead of doing `tofu workspace select your_workspace`, it is possible to use this environment variable. Using TF\_WORKSPACE allow and override workspace selection. For example: Code Block export TF_WORKSPACE=your_workspace Using this environment variable is recommended only for non-interactive usage, since in a local shell environment it can be easy to forget the variable is set and apply changes to the wrong state. For more information regarding workspaces, check out the section on [Using Workspaces](https://opentofu.org/docs/v1.11/language/state/workspaces/) . TF\_IN\_AUTOMATION[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_in_automation "Direct link to TF_IN_AUTOMATION") -------------------------------------------------------------------------------------------------------------------------------------------- If `TF_IN_AUTOMATION` is set to any non-empty value, OpenTofu adjusts its output to avoid suggesting specific commands to run next. This can make the output more consistent and less confusing in workflows where users don't directly execute OpenTofu commands, like in CI systems or other wrapping applications. This is a purely cosmetic change to OpenTofu's human-readable output, and the exact output differences can change between minor OpenTofu versions. TF\_REGISTRY\_DISCOVERY\_RETRY[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_registry_discovery_retry "Direct link to TF_REGISTRY_DISCOVERY_RETRY") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Equivalent to the `retry_count` setting in the [Registry Protocol Settings](https://opentofu.org/docs/v1.11/cli/config/config-file/#registry-protocol-settings) . TF\_REGISTRY\_CLIENT\_TIMEOUT[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_registry_client_timeout "Direct link to TF_REGISTRY_CLIENT_TIMEOUT") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Equivalent to the `request_timeout_seconds` setting in the [Registry Protocol Settings](https://opentofu.org/docs/v1.11/cli/config/config-file/#registry-protocol-settings) . TF\_CLI\_CONFIG\_FILE[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_cli_config_file "Direct link to TF_CLI_CONFIG_FILE") --------------------------------------------------------------------------------------------------------------------------------------------------- The location of the [OpenTofu CLI configuration file](https://opentofu.org/docs/v1.11/cli/config/config-file/) . Code Block export TF_CLI_CONFIG_FILE="$HOME/.tofurc-custom" TF\_PLUGIN\_CACHE\_DIR[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_plugin_cache_dir "Direct link to TF_PLUGIN_CACHE_DIR") ------------------------------------------------------------------------------------------------------------------------------------------------------ The `TF_PLUGIN_CACHE_DIR` environment variable is an alternative way to set [the `plugin_cache_dir` setting in the CLI configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-plugin-cache) . You can also use `TF_PLUGIN_CACHE_MAY_BREAK_DEPENDENCY_LOCK_FILE` to activate [the transitional compatibility setting `plugin_cache_may_break_dependency_lock_file`](https://opentofu.org/docs/v1.11/cli/config/config-file/#allowing-the-provider-plugin-cache-to-break-the-dependency-lock-file) . TF\_IGNORE[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_ignore "Direct link to TF_IGNORE") ---------------------------------------------------------------------------------------------------------------------- If `TF_IGNORE` is set to "trace", OpenTofu will output debug messages to display ignored files and folders. This is useful when debugging large repositories with `.terraformignore` files. Code Block export TF_IGNORE=trace For more details on `.terraformignore`, please see [Excluding Files from Upload with .terraformignore](https://opentofu.org/docs/v1.11/language/settings/backends/remote/#excluding-files-from-upload-with-terraformignore) . TF\_PROVIDER\_DOWNLOAD\_RETRY[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_provider_download_retry "Direct link to TF_PROVIDER_DOWNLOAD_RETRY") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Set `TF_PROVIDER_DOWNLOAD_RETRY` to configure the max number of request retries the remote provider client will attempt for client connection errors or 500-range responses that are safe to retry. Note This will be used only for the methods without the argument `download_retry_count` specified in [OpenTofu CLI configuration file](https://opentofu.org/docs/v1.11/cli/config/config-file/#explicit-installation-method-configuration) . Code Block export TF_PROVIDER_DOWNLOAD_RETRY=3 TF\_STATE\_PERSIST\_INTERVAL[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_state_persist_interval "Direct link to TF_STATE_PERSIST_INTERVAL") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Set `TF_STATE_PERSIST_INTERVAL` to configure the interval (in seconds) between state persistence. Increased interval could be useful when working with huge states (> 100k resources) where upload to a cloud service could take a significant amount of time. Default persistence interval is 20 seconds (it also the lowest possible value for this parameter). The following command sets persistence interval to 5 minutes (300 seconds): Code Block export TF_STATE_PERSIST_INTERVAL=300 Cloud Backend CLI Integration[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#cloud-backend-cli-integration "Direct link to Cloud Backend CLI Integration") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The CLI integration with cloud backends lets you use them on the command line. The integration requires including a `cloud` block in your OpenTofu configuration. You can define its arguments directly in your configuration file or supply them through environment variables, which can be useful for non-interactive workflows like Continuous Integration (CI). Refer to [Cloud Backend Settings](https://opentofu.org/docs/v1.11/cli/cloud/settings/#environment-variables) for a full list of `cloud` block environment variables. TF\_ENCRYPTION[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_encryption "Direct link to TF_ENCRYPTION") ---------------------------------------------------------------------------------------------------------------------------------- The `TF_ENCRYPTION` environment variable is an alternate method of specifying the contents of the `terraform { encryption {} }` block. If provided, it will be parsed as either HCL or JSON and override configuration present in the .tf config files. Code Block # Add/Override encryption key_provider.static.mykpexport TF_ENCRYPTION='key_provider "static" "mykp" { key = "6f6f706830656f67686f6834616872756f3751756165686565796f6f72653169" }' Warning If the key (or similar) has non-alphanumeric characters in it, beware that your shell may not interpret them literally. Special characters are shell dependent, but some common examples are dollar signs for variable interpolation or backslashes for character escaping. Make sure your secret doesn't get changed by your shell without you realizing. This is also shell dependent, but common ways of avoiding this are using single quotes or escaping special characters with a backslash. TOFU\_CPU\_PROFILE[​](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tofu_cpu_profile "Direct link to TOFU_CPU_PROFILE") -------------------------------------------------------------------------------------------------------------------------------------------- Set `TOFU_CPU_PROFILE` to instruct OpenTofu to write a [Go pprof file](https://pkg.go.dev/runtime/pprof) . These profiles can be used to help developers identify hot-spots in OpenTofu's codebase that slow down execution. It pairs well with the more granular and well structured OpenTelemetry tracing (available in OpenTofu 1.10.0). For more information on profiling in Go, see [https://go.dev/blog/pprof](https://go.dev/blog/pprof) . As this uses the go runtime's pprof tooling directly, is not covered under the compatibility promise and is subject to change / removal at any time. Code Block TOFU_CPU_PROFILE=./tofu.pprof tofu plango tool pprof -http ./tofu.pprof * [TF\_LOG](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_log) * [TF\_LOG\_PATH](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_log_path) * [TF\_INPUT](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_input) * [TF\_VAR\_name](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_var_name) * [TF\_CLI\_ARGS and TF\_CLI\_ARGS\_name](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_cli_args-and-tf_cli_args_name) * [TF\_DATA\_DIR](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_data_dir) * [TF\_WORKSPACE](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_workspace) * [TF\_IN\_AUTOMATION](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_in_automation) * [TF\_REGISTRY\_DISCOVERY\_RETRY](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_registry_discovery_retry) * [TF\_REGISTRY\_CLIENT\_TIMEOUT](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_registry_client_timeout) * [TF\_CLI\_CONFIG\_FILE](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_cli_config_file) * [TF\_PLUGIN\_CACHE\_DIR](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_plugin_cache_dir) * [TF\_IGNORE](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_ignore) * [TF\_PROVIDER\_DOWNLOAD\_RETRY](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_provider_download_retry) * [TF\_STATE\_PERSIST\_INTERVAL](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_state_persist_interval) * [Cloud Backend CLI Integration](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#cloud-backend-cli-integration) * [TF\_ENCRYPTION](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_encryption) * [TOFU\_CPU\_PROFILE](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tofu_cpu_profile) --- # Provider Registry Protocol | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Provider Registry Protocol ========================== The provider registry protocol is what OpenTofu CLI uses to discover metadata about providers available for installation and to locate the distribution packages for a selected provider. The primary implementation of this protocol is the public [OpenTofu Registry](https://registry.opentofu.org/) at `registry.opentofu.org`. By writing and deploying your own implementation of this protocol, you can create a separate _origin registry_ to distribute your own providers, as an alternative to publishing them on the public OpenTofu Registry. This page describes the provider _registry_ protocol, which is the protocol for finding providers available for installation. It _doesn't_ describe the API that provider plugins themselves implement to serve requests from OpenTofu CLI at runtime. For more information on the provider API, see the OpenTofu SDK documentation. Provider Addresses[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#provider-addresses "Direct link to Provider Addresses") ---------------------------------------------------------------------------------------------------------------------------------------------------- Each OpenTofu provider has an associated address which uniquely identifies it within OpenTofu. A provider address has the syntax `hostname/namespace/type`, where: * `hostname` is the registry host that the provider is considered to have originated from, and the default location OpenTofu will consult for information about the provider [unless overridden in the CLI configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation) . * `namespace` is the name of a namespace, unique on a particular hostname, that can contain one or more providers that are somehow related. On the public OpenTofu Registry the "namespace" represents the organization that is packaging and distributing the provider. * `type` is the provider type, like "azurerm", "aws", "google", "dns", etc. A provider type is unique within a particular hostname and namespace. The `hostname/` portion of a provider address (including its slash delimiter) is optional, and if omitted defaults to `registry.opentofu.org/`. For example: * `hashicorp/aws` is a shorthand for `registry.opentofu.org/hashicorp/aws`, which is the official AWS provider published by HashiCorp. * `example/foo` is a shorthand for `registry.opentofu.org/example/foo`, which is a hypothetical third-party provider published on the public OpenTofu Registry. * `example.com/bar/baz` is a hypothetical third-party provider published at a third-party provider registry on `example.com`. If you intend only to share a provider you've developed for use by all OpenTofu users, please consider publishing it into the public [OpenTofu Registry](https://registry.opentofu.org/) , which will make your provider discoverable. You only need to implement this provider registry protocol if you wish to publish providers whose addresses include a different hostname that is under your control. OpenTofu uses the full address (after normalization to always include a hostname) as its global identifier for providers internally, and so it's important to note that re-uploading the `examplecorp/azurerm` provider into another namespace or publishing it on a different hostname will cause OpenTofu to see it as an entirely separate provider that will _not_ be usable by modules that declare a dependency on `examplecorp/azurerm`. If your goal is to create an alternative local distribution source for an existing provider -- that is, a _mirror_ of the provider -- refer to [the provider installation method configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation) instead. Provider Versions[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#provider-versions "Direct link to Provider Versions") ------------------------------------------------------------------------------------------------------------------------------------------------- Each distinct provider address has associated with it a set of versions, each of which has an associated version number. OpenTofu assumes version numbers follow the [Semantic Versioning 2.0](https://semver.org/) conventions, with the schema and behavior of the provider as documented from the perspective of an end-user of OpenTofu serving as the "public API". All available versions for a particular provider address are considered to be the same provider by OpenTofu. Each OpenTofu configuration selects only one version of each provider for use in the entire configuration, so the version constraints across all modules are considered together for the purposes of version selection. Service Discovery[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#service-discovery "Direct link to Service Discovery") ------------------------------------------------------------------------------------------------------------------------------------------------- The providers protocol begins with OpenTofu CLI using [OpenTofu's remote service discovery protocol](https://opentofu.org/docs/v1.11/internals/remote-service-discovery/) , with the hostname in the provider address acting as the "User-facing Hostname". The service identifier for the provider registry protocol is `providers.v1`. Its associated string value is the base URL for the relative URLs defined in the sections that follow. For example, the service discovery document for a host that _only_ implements the provider registry protocol might contain the following: Code Block { "providers.v1": "/tofu/providers/v1/"} If the given URL is a relative URL then OpenTofu will interpret it as relative to the discovery document itself. The specific provider registry protocol endpoints are defined as URLs relative to the given base URL, and so the specified base URL should generally end with a slash to ensure that those relative paths will be resolved as expected. The following sections describe the various operations that a provider registry must implement to be compatible with OpenTofu CLI's provider installer. The indicated URLs are all relative to the URL resulting from service discovery, as described above. We use a hypothetical URL for a provider registry, assuming that the caller already performed service discovery on a hypothetical `registry.example.io` to learn the base URL. The URLs are shown with the convention that a path portion with a colon `:` prefix is a placeholder for a dynamically-selected value, while all other path portions are literal. For example, in `:namespace/:type/versions`, the first two path portions are placeholders while the third is literally the string "versions". List Available Versions[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#list-available-versions "Direct link to List Available Versions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- This operation determines which versions are currently available for a particular provider. | Method | Path | Produces | | --- | --- | --- | | `GET` | `:namespace/:type/versions` | `application/json` | ### Parameters[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#parameters "Direct link to Parameters") * `namespace` (required): the namespace portion of the address of the requested provider. * `type` (required): the type portion of the address of the requested provider. ### Sample Request[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#sample-request "Direct link to Sample Request") Code Block curl 'https://registry.opentofu.org/v1/providers/examplecorp/random/versions' ### Sample Response[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#sample-response "Direct link to Sample Response") Code Block { "versions": [ { "version": "2.0.0", "protocols": ["4.0", "5.1"], "platforms": [ {"os": "darwin", "arch": "amd64"}, {"os": "linux", "arch": "amd64"}, {"os": "linux", "arch": "arm"}, {"os": "windows", "arch": "amd64"} ] }, { "version": "2.0.1", "protocols": ["5.2"], "platforms": [ {"os": "darwin", "arch": "amd64"}, {"os": "linux", "arch": "amd64"}, {"os": "linux", "arch": "arm"}, {"os": "windows", "arch": "amd64"} ] } ]} ### Response Properties[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#response-properties "Direct link to Response Properties") A successful result is a JSON object containing a single property `versions`. `versions` is an array of objects that each describe one available version, with the following properties: * `version` (required): the version number this object is describing, using the semantic versioning string notation. `version` must be unique across all objects in the response. * `protocols` (recommended): an array of OpenTofu provider API versions that this version supports, each given in `MAJOR.MINOR` format where each major version appears only once and the given minor version is the highest minor version supported. For example, `5.1` means that the provider supports both protocol `5.0` and protocol `5.1`. OpenTofu uses this information, when available, to provide hints to users about upgrading or downgrading their version of a particular provider to work with their current version of OpenTofu, if their currently-selected versions are not compatible. Which API versions are supported is, for most providers, decided by which version of the Terraform SDK they are built against. Consult the Terraform SDK documentation for more information. * `platforms` (recommended): an array of objects describing platforms that have packages available for this version. OpenTofu may use this information, when available, to provide hints to users about upgrading or downgrading their version of a particular provider for compatibility with their current platform. The `platforms` objects have properties `os` and `arch`, whose values match the properties of the same name in the response to [Find a Provider Package](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#find-a-provider-package) . Return `404 Not Found` to signal that the registry does not have a provider with the given namespace and type. Find a Provider Package[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#find-a-provider-package "Direct link to Find a Provider Package") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- This operation returns the download URL of and associated metadata about the distribution package for a particular version of a provider for a particular operating system and architecture. OpenTofu CLI uses this operation after it has selected the newest available version matching the configured version constraints, in order to find the zip archive containing the plugin itself. | Method | Path | Produces | | --- | --- | --- | | `GET` | `:namespace/:type/:version/download/:os/:arch` | `application/json` | ### Parameters[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#parameters-1 "Direct link to Parameters") * `namespace` (required): the namespace portion of the address of the requested provider. * `type` (required): the type portion of the address of the requested provider. * `version` (required): the version selected to download. This will exactly match one of the version strings returned from a previous call to [List Available Versions](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#list-available-versions) . * `os` (required): a keyword identifying the operating system that the returned package should be compatible with, like "linux" or "darwin". * `arch` (required): a keyword identifying the CPU architecture that the returned package should be compatible with, like "amd64" or "arm". ### Sample Request[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#sample-request-1 "Direct link to Sample Request") Code Block curl 'https://registry.opentofu.org/v1/providers/examplecorp/random/2.0.0/download/linux/amd64' ### Sample Response[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#sample-response-1 "Direct link to Sample Response") Code Block { "protocols": ["4.0", "5.1"], "os": "linux", "arch": "amd64", "filename": "terraform-provider-random_2.0.0_linux_amd64.zip", "download_url": "https://releases.example.com/terraform-provider-random/2.0.0/terraform-provider-random_2.0.0_linux_amd64.zip", "shasums_url": "https://releases.example.com/terraform-provider-random/2.0.0/terraform-provider-random_2.0.0_SHA256SUMS", "shasums_signature_url": "https://releases.example.com/terraform-provider-random/2.0.0/terraform-provider-random_2.0.0_SHA256SUMS.sig", "shasum": "5f9c7aa76b7c34d722fc9123208e26b22d60440cb47150dd04733b9b94f4541a", "signing_keys": { "gpg_public_keys": [ { "key_id": "51852D87348FFC4C", "ascii_armor": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1\n\nmQENBFMORM0BCADBRyKO1MhCirazOSVwcfTr1xUxjPvfxD3hjUwHtjsOy/bT6p9f\nW2mRPfwnq2JB5As+paL3UGDsSRDnK9KAxQb0NNF4+eVhr/EJ18s3wwXXDMjpIifq\nfIm2WyH3G+aRLTLPIpscUNKDyxFOUbsmgXAmJ46Re1fn8uKxKRHbfa39aeuEYWFA\n3drdL1WoUngvED7f+RnKBK2G6ZEpO+LDovQk19xGjiMTtPJrjMjZJ3QXqPvx5wca\nKSZLr4lMTuoTI/ZXyZy5bD4tShiZz6KcyX27cD70q2iRcEZ0poLKHyEIDAi3TM5k\nSwbbWBFd5RNPOR0qzrb/0p9ksKK48IIfH2FvABEBAAG0K0hhc2hpQ29ycCBTZWN1\ncml0eSA8c2VjdXJpdHlAaGFzaGljb3JwLmNvbT6JATgEEwECACIFAlMORM0CGwMG\nCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEFGFLYc0j/xMyWIIAIPhcVqiQ59n\nJc07gjUX0SWBJAxEG1lKxfzS4Xp+57h2xxTpdotGQ1fZwsihaIqow337YHQI3q0i\nSqV534Ms+j/tU7X8sq11xFJIeEVG8PASRCwmryUwghFKPlHETQ8jJ+Y8+1asRydi\npsP3B/5Mjhqv/uOK+Vy3zAyIpyDOMtIpOVfjSpCplVRdtSTFWBu9Em7j5I2HMn1w\nsJZnJgXKpybpibGiiTtmnFLOwibmprSu04rsnP4ncdC2XRD4wIjoyA+4PKgX3sCO\nklEzKryWYBmLkJOMDdo52LttP3279s7XrkLEE7ia0fXa2c12EQ0f0DQ1tGUvyVEW\nWmJVccm5bq25AQ0EUw5EzQEIANaPUY04/g7AmYkOMjaCZ6iTp9hB5Rsj/4ee/ln9\nwArzRO9+3eejLWh53FoN1rO+su7tiXJA5YAzVy6tuolrqjM8DBztPxdLBbEi4V+j\n2tK0dATdBQBHEh3OJApO2UBtcjaZBT31zrG9K55D+CrcgIVEHAKY8Cb4kLBkb5wM\nskn+DrASKU0BNIV1qRsxfiUdQHZfSqtp004nrql1lbFMLFEuiY8FZrkkQ9qduixo\nmTT6f34/oiY+Jam3zCK7RDN/OjuWheIPGj/Qbx9JuNiwgX6yRj7OE1tjUx6d8g9y\n0H1fmLJbb3WZZbuuGFnK6qrE3bGeY8+AWaJAZ37wpWh1p0cAEQEAAYkBHwQYAQIA\nCQUCUw5EzQIbDAAKCRBRhS2HNI/8TJntCAClU7TOO/X053eKF1jqNW4A1qpxctVc\nz8eTcY8Om5O4f6a/rfxfNFKn9Qyja/OG1xWNobETy7MiMXYjaa8uUx5iFy6kMVaP\n0BXJ59NLZjMARGw6lVTYDTIvzqqqwLxgliSDfSnqUhubGwvykANPO+93BBx89MRG\nunNoYGXtPlhNFrAsB1VR8+EyKLv2HQtGCPSFBhrjuzH3gxGibNDDdFQLxxuJWepJ\nEK1UbTS4ms0NgZ2Uknqn1WRU1Ki7rE4sTy68iZtWpKQXZEJa0IGnuI2sSINGcXCJ\noEIgXTMyCILo34Fa/C6VCm2WBgz9zZO8/rHIiQm1J5zqz0DrDwKBUM9C\n=LYpS\n-----END PGP PUBLIC KEY BLOCK-----", "trust_signature": "", "source": "ExampleCorp", "source_url": "https://www.examplecorp.com/security.html" } ] }} ### Response Properties[​](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#response-properties-1 "Direct link to Response Properties") A successful result is a JSON object with the following properties: * `protocols` (required): an array of OpenTofu provider API versions that the provider supports, in the same format as for [List Available Versions](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#list-available-versions) . While this property is optional when listing available options, it is _required_ for describing an individual provider package so that OpenTofu CLI can avoid downloading a package that will not be compatible with it. * `os` (required): this must echo back the `os` parameter from the request. * `arch` (required): this must echo back the `arch` parameter from the request. * `filename` (required): the filename for this provider's zip archive as recorded in the "shasums" document, so that OpenTofu CLI can determine which of the given checksums should be used for this specific package. * `download_url` (required): a URL from which OpenTofu can retrieve the provider's zip archive. If this is a relative URL then it will be resolved relative to the URL that returned the containing JSON object. * `shasums_url` (required): a URL from which OpenTofu can retrieve a text document recording expected SHA256 checksums for this package and possibly other packages for the same provider version on other platforms. The indicated document must be in the format generated by the `sha256` command available on many Unix systems, with one entry recording the same filename given in the `filename` property (case sensitive). * `shasums_signature_url` (required): a URL from which OpenTofu can retrieve a binary, detached GPG signature for the document at `shasums_url`, signed by one of the keys indicated in the `signing_keys` property. * `shasum` (required): the SHA256 checksum for this provider's zip archive as recorded in the shasums document. * `signing_keys` (required): an object describing signing keys for this provider package, one of which must have been used to produce the signature at `shasums_signature_url`. The object has the following nested properties: * `gpg_public_keys` (required): an array of objects, each describing one GPG signing key that is allowed to sign the checksums for this provider version. At least one element must be included, representing the key that produced the signature at `shasums_signature_url`. These objects have the following nested properties: * `key_id` (required): uppercase-hexadecimal-formatted ID for this GPG key * `ascii_armor` (required): an "ascii-armor" encoding of the **public key** associated with this GPG key. Return `404 Not Found` to signal that the given provider version isn't available for the requested operating system and/or architecture. OpenTofu CLI will only attempt to download versions that it has previously seen in response to [List Available Versions](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#list-available-versions) . * [Provider Addresses](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#provider-addresses) * [Provider Versions](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#provider-versions) * [Service Discovery](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#service-discovery) * [List Available Versions](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#list-available-versions) * [Parameters](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#parameters) * [Sample Request](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#sample-request) * [Sample Response](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#sample-response) * [Response Properties](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#response-properties) * [Find a Provider Package](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#find-a-provider-package) * [Parameters](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#parameters-1) * [Sample Request](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#sample-request-1) * [Sample Response](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#sample-response-1) * [Response Properties](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/#response-properties-1) --- # Managing Workspaces | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/workspaces/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Managing Workspaces =================== Workspaces in the OpenTofu CLI refer to separate instances of [state data](https://opentofu.org/docs/v1.11/language/state/) inside the same OpenTofu working directory. They are distinctly different from workspaces in a cloud backend, which each have their own OpenTofu configuration and function as separate working directories. OpenTofu relies on state to associate resources with real-world objects. When you run the same configuration multiple times with separate state data, OpenTofu can manage multiple sets of non-overlapping resources. Workspaces can be helpful for specific [use cases](https://opentofu.org/docs/v1.11/cli/workspaces/#use-cases) , but they are not required to use the OpenTofu CLI. We recommend using [alternative approaches](https://opentofu.org/docs/v1.11/cli/workspaces/#alternatives-to-workspaces) for complex deployments requiring separate credentials and access controls. Managing CLI Workspaces[​](https://opentofu.org/docs/v1.11/cli/workspaces/#managing-cli-workspaces "Direct link to Managing CLI Workspaces") --------------------------------------------------------------------------------------------------------------------------------------------- Every [initialized working directory](https://opentofu.org/docs/v1.11/cli/init/) starts with one workspace named `default`. Use the [`tofu workspace list`](https://opentofu.org/docs/v1.11/cli/commands/workspace/list/) , [`tofu workspace new`](https://opentofu.org/docs/v1.11/cli/commands/workspace/new/) , and [`tofu workspace delete`](https://opentofu.org/docs/v1.11/cli/commands/workspace/delete/) commands to manage the available workspaces in the current working directory. Use [the `tofu workspace select` command](https://opentofu.org/docs/v1.11/cli/commands/workspace/select/) to change the currently selected workspace. For a given working directory, you can only select one workspace at a time. Most OpenTofu commands only interact with the currently selected workspace. This includes [provisioning](https://opentofu.org/docs/v1.11/cli/run/) and [state manipulation](https://opentofu.org/docs/v1.11/cli/state/) . When you provision infrastructure in each workspace, you usually need to manually specify different [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) to differentiate each collection. For example, you might deploy test infrastructure to a different region. Use Cases[​](https://opentofu.org/docs/v1.11/cli/workspaces/#use-cases "Direct link to Use Cases") --------------------------------------------------------------------------------------------------- You can create multiple [working directories](https://opentofu.org/docs/v1.11/cli/init/) to maintain multiple instances of a configuration with completely separate state data. However, OpenTofu installs a separate cache of plugins and modules for each working directory, so maintaining multiple directories can waste bandwidth and disk space. This approach also requires extra tasks like updating configuration from version control for each directory separately and reinitializing each directory when you change the configuration. Workspaces are convenient because they let you create different sets of infrastructure with the same working copy of your configuration and the same plugin and module caches. A common use for multiple workspaces is to create a parallel, distinct copy of a set of infrastructure to test a set of changes before modifying production infrastructure. Non-default workspaces are often related to feature branches in version control. The default workspace might correspond to the `main` or `trunk` branch, which describes the intended state of production infrastructure. When a developer creates a feature branch for a change, they might also create a corresponding workspace and deploy into it a temporary copy of the main infrastructure. They can then test changes on the copy without affecting the production infrastructure. Once the change is merged and deployed to the default workspace, they destroy the test infrastructure and delete the temporary workspace. ### When Not to Use Multiple Workspaces[​](https://opentofu.org/docs/v1.11/cli/workspaces/#when-not-to-use-multiple-workspaces "Direct link to When Not to Use Multiple Workspaces") Workspaces let you quickly switch between multiple instances of a **single configuration** within its **single backend**. They are not designed to solve all problems. When using OpenTofu to manage larger systems, you should create separate OpenTofu configurations that correspond to architectural boundaries within the system. This lets teams manage different components separately. Workspaces alone are not a suitable tool for system decomposition because each subsystem should have its own separate configuration and backend. In particular, organizations commonly want to create a strong separation between multiple deployments of the same infrastructure serving different development stages or different internal teams. In this case, the backend for each deployment often has different credentials and access controls. CLI workspaces within a working directory use the same backend, so they are not a suitable isolation mechanism for this scenario. Alternatives to Workspaces[​](https://opentofu.org/docs/v1.11/cli/workspaces/#alternatives-to-workspaces "Direct link to Alternatives to Workspaces") ------------------------------------------------------------------------------------------------------------------------------------------------------ Instead of creating CLI workspaces, you can use one or more [re-usable modules](https://opentofu.org/docs/v1.11/language/modules/develop/) to represent the common elements and then represent each instance as a separate configuration that instantiates those common elements in the context of a different [backend](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/) . The root module of each configuration consists only of a backend configuration and a small number of `module` blocks with arguments describing any small differences between the deployments. When multiple configurations represent distinct system components rather than multiple deployments, you can pass data from one component to another using paired resources types and data sources. * If you have a configuration management system accessible from all configurations, then one can use a `resource` to export variables, while another configuration can use a `datasource` to import them. * In systems that support user-defined labels or tags, use a tagging convention to make resources automatically discoverable. For example, use [the `aws_vpc` resource type](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc) to assign suitable tags and then [the `aws_vpc` data source](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) to query by those tags in other configurations. * For server addresses, use a provider-specific resource to create a DNS record with a predictable name. Then you can either use that name directly or use [the `dns` provider](https://registry.terraform.io/providers/hashicorp/dns/latest/docs) to retrieve the published addresses in other configurations. * If you store a OpenTofu state for one configuration in a remote backend that other configurations can access, then the other configurations can use [`terraform_remote_state`](https://opentofu.org/docs/v1.11/language/state/remote-state-data/) to directly consume its root module outputs. This setup creates a tighter coupling between configurations, and the root configuration does not need to publish its results in a separate system. Workspace Internals[​](https://opentofu.org/docs/v1.11/cli/workspaces/#workspace-internals "Direct link to Workspace Internals") --------------------------------------------------------------------------------------------------------------------------------- Workspaces are technically equivalent to renaming your state file. OpenTofu then includes a set of protections and support for remote state. Workspaces are also meant to be a shared resource. They are not private, unless you use purely local state and do not commit your state to version control. For local state, OpenTofu stores the workspace states in a directory called `terraform.tfstate.d`. This directory should be treated similarly to local-only `terraform.tfstate`. Some teams commit these files to version control, but we recommend using a remote backend instead when there are multiple collaborators. For [remote state](https://opentofu.org/docs/v1.11/language/state/remote/) , the workspaces are stored directly in the configured [backend](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/) . For example, if you use [Consul](https://opentofu.org/docs/v1.11/language/settings/backends/consul/) , the workspaces are stored by appending the workspace name to the state path. To ensure that workspace names are stored correctly and safely in all backends, the name must be valid to use in a URL path segment without escaping. OpenTofu stores the current workspace name locally in the ignored `.terraform` directory. This allows multiple team members to work on different workspaces concurrently. Workspace names are also attached to associated remote workspaces in a cloud backend. For more details about workspace names in cloud backends, refer to the [CLI Integration (recommended)](https://opentofu.org/docs/v1.11/cli/cloud/settings/#arguments) and [remote backend](https://opentofu.org/docs/v1.11/language/settings/backends/remote/#workspaces) and documentation. * [Managing CLI Workspaces](https://opentofu.org/docs/v1.11/cli/workspaces/#managing-cli-workspaces) * [Use Cases](https://opentofu.org/docs/v1.11/cli/workspaces/#use-cases) * [When Not to Use Multiple Workspaces](https://opentofu.org/docs/v1.11/cli/workspaces/#when-not-to-use-multiple-workspaces) * [Alternatives to Workspaces](https://opentofu.org/docs/v1.11/cli/workspaces/#alternatives-to-workspaces) * [Workspace Internals](https://opentofu.org/docs/v1.11/cli/workspaces/#workspace-internals) --- # Installing OpenTofu on .deb-based Linux (Debian, Ubuntu, etc.) | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/install/deb/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Installing OpenTofu on .deb-based Linux (Debian, Ubuntu, etc.) ============================================================== [Thank you to Buildkite for sponsoring the OpenTofu package hosting.](https://buildkite.com/) You can install OpenTofu from our Debian repository by following the step-by-step instructions below. Installing using the installer[​](https://opentofu.org/docs/v1.11/intro/install/deb/#installing-using-the-installer "Direct link to Installing using the installer") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can use the OpenTofu installer script to run the installation. Code Block # Download the installer script:curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh -o install-opentofu.sh# Alternatively: wget --secure-protocol=TLSv1_2 --https-only https://get.opentofu.org/install-opentofu.sh -O install-opentofu.sh# Give it execution permissions:chmod +x install-opentofu.sh# Please inspect the downloaded script# Run the installer:./install-opentofu.sh --install-method deb# Remove the installer:rm -f install-opentofu.sh Step-by-step instructions[​](https://opentofu.org/docs/v1.11/intro/install/deb/#step-by-step-instructions "Direct link to Step-by-step instructions") ------------------------------------------------------------------------------------------------------------------------------------------------------ The following steps explain how to set up the OpenTofu Debian repositories. These instructions should work on most Debian-based Linux systems. ### Installing tooling[​](https://opentofu.org/docs/v1.11/intro/install/deb/#installing-tooling "Direct link to Installing tooling") In order to add the repositories, you will need to install some tooling. On most Debian-based operating systems, these tools will already be installed. Code Block sudo apt-get updatesudo apt-get install -y apt-transport-https ca-certificates curl gnupg ### Set up the OpenTofu repository[​](https://opentofu.org/docs/v1.11/intro/install/deb/#set-up-the-opentofu-repository "Direct link to Set up the OpenTofu repository") First, you need to make sure you have a copy of the OpenTofu GPG key. This verifies that your packages have indeed been created using the official pipeline and have not been tampered with. Code Block sudo install -m 0755 -d /etc/apt/keyringscurl -fsSL https://get.opentofu.org/opentofu.gpg | sudo tee /etc/apt/keyrings/opentofu.gpg >/dev/nullcurl -fsSL https://packages.opentofu.org/opentofu/tofu/gpgkey | sudo gpg --no-tty --batch --dearmor -o /etc/apt/keyrings/opentofu-repo.gpg >/dev/nullsudo chmod a+r /etc/apt/keyrings/opentofu.gpg /etc/apt/keyrings/opentofu-repo.gpg Now you have to create the OpenTofu source list. Code Block echo \ "deb [signed-by=/etc/apt/keyrings/opentofu.gpg,/etc/apt/keyrings/opentofu-repo.gpg] https://packages.opentofu.org/opentofu/tofu/any/ any maindeb-src [signed-by=/etc/apt/keyrings/opentofu.gpg,/etc/apt/keyrings/opentofu-repo.gpg] https://packages.opentofu.org/opentofu/tofu/any/ any main" | \ sudo tee /etc/apt/sources.list.d/opentofu.list > /dev/nullsudo chmod a+r /etc/apt/sources.list.d/opentofu.list ### Installing OpenTofu[​](https://opentofu.org/docs/v1.11/intro/install/deb/#installing-opentofu "Direct link to Installing OpenTofu") Finally, you can install OpenTofu: Code Block sudo apt-get updatesudo apt-get install -y tofu * [Installing using the installer](https://opentofu.org/docs/v1.11/intro/install/deb/#installing-using-the-installer) * [Step-by-step instructions](https://opentofu.org/docs/v1.11/intro/install/deb/#step-by-step-instructions) * [Installing tooling](https://opentofu.org/docs/v1.11/intro/install/deb/#installing-tooling) * [Set up the OpenTofu repository](https://opentofu.org/docs/v1.11/intro/install/deb/#set-up-the-opentofu-repository) * [Installing OpenTofu](https://opentofu.org/docs/v1.11/intro/install/deb/#installing-opentofu) --- # Inspecting Infrastructure | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/inspect/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Inspecting Infrastructure ========================= OpenTofu configurations and state data include some highly structured information about the resources they manage; this includes dependency information, outputs (which are pieces of generated or discovered data that the configuration's author considers important enough to surface to users), and more. OpenTofu CLI includes some commands for inspecting or transforming this data. You can use these to integrate other tools with OpenTofu's infrastructure data, or just to gain a deeper or more holistic understanding of your infrastructure. * [The `tofu graph` command](https://opentofu.org/docs/v1.11/cli/commands/graph/) creates a visual representation of a configuration or a set of planned changes. * [The `tofu output` command](https://opentofu.org/docs/v1.11/cli/commands/output/) can get the values for the top-level [output values](https://opentofu.org/docs/v1.11/language/values/outputs/) of a configuration, which are often helpful when making use of the infrastructure OpenTofu has provisioned. * [The `tofu show` command](https://opentofu.org/docs/v1.11/cli/commands/show/) can generate human-readable versions of a state file or plan file, or generate machine-readable versions that can be integrated with other tools. * [The `tofu state list` command](https://opentofu.org/docs/v1.11/cli/commands/state/list/) can list the resources being managed by the current working directory and workspace, providing a complete or filtered list. * [The `tofu state show` command](https://opentofu.org/docs/v1.11/cli/commands/state/show/) can print all of the attributes of a given resource being managed by the current working directory and workspace, including generated read-only attributes like the unique ID assigned by the cloud provider. --- # The terraform_remote_state Data Source | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page The `terraform_remote_state` Data Source ======================================== The `terraform_remote_state` data source uses the latest state snapshot from a specified state backend to retrieve the root module output values from some other OpenTofu configuration. You can use the `terraform_remote_state` data source without requiring or configuring a provider. It is always available through a built-in provider with the [source address](https://opentofu.org/docs/v1.10/language/providers/requirements/#source-addresses) `terraform.io/builtin/terraform`. That provider does not include any other resources or data sources. Warning `terraform_remote_state` does not respect the sensitivity of source state snapshots. Use caution when referencing state with sensitive root module output values. Warning Be careful when using [state encryption](https://opentofu.org/docs/v1.10/language/state/encryption/) ! Sharing encrypted state between projects requires careful coordination of metadata keys. Please read the [Remote state data sources](https://opentofu.org/docs/v1.10/language/state/encryption/#remote-state-data-sources) section of the state encryption guide for details. Alternative Ways to Share Data Between Configurations[​](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#alternative-ways-to-share-data-between-configurations "Direct link to Alternative Ways to Share Data Between Configurations") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Sharing data with root module outputs is convenient, but it has drawbacks. Although `terraform_remote_state` only exposes output values, its user must have access to the entire state snapshot, which often includes some sensitive information. When possible, we recommend explicitly publishing data for external consumption to a separate location instead of accessing it via remote state. This lets you apply different access controls for shared information and state snapshots. To share data explicitly between configurations, you can use pairs of managed resource types and data sources in various providers, including (but not limited to) the following: | System | Publish with... | Read with... | | --- | --- | --- | | Alibaba Cloud DNS
(for IP addresses and hostnames) | [`alicloud_alidns_record` resource type](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/alidns_record) | Normal DNS lookups, or [the `dns` provider](https://registry.terraform.io/providers/hashicorp/dns/latest/docs) | | Amazon Route53
(for IP addresses and hostnames) | [`aws_route53_record` resource type](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | Normal DNS lookups, or [the `dns` provider](https://registry.terraform.io/providers/hashicorp/dns/latest/docs) | | Amazon S3 | [`aws_s3_object` resource type](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_object) | [`aws_s3_object` data source](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/s3_object) | | Amazon SSM Parameter Store | [`aws_ssm_parameter` resource type](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | [`aws_ssm_parameter` data source](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | | Azure Automation | [`azurerm_automation_variable_string` resource type](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/automation_variable_string) | [`azurerm_automation_variable_string` data source](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/automation_variable_string) | | Azure DNS
(for IP addresses and hostnames) | [`azurerm_dns_a_record` resource type](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/dns_a_record)
, etc | Normal DNS lookups, or [the `dns` provider](https://registry.terraform.io/providers/hashicorp/dns/latest/docs) | | Google Cloud DNS
(for IP addresses and hostnames) | [`google_dns_record_set` resource type](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/dns_record_set) | Normal DNS lookups, or [the `dns` provider](https://registry.terraform.io/providers/hashicorp/dns/latest/docs) | | Google Cloud Storage | [`google_storage_bucket_object` resource type](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket_object) | [`google_storage_bucket_object` data source](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/storage_bucket_object)
and [`http` data source](https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http) | | HashiCorp Consul | [`consul_key_prefix` resource type](https://registry.terraform.io/providers/hashicorp/consul/latest/docs/resources/key_prefix) | [`consul_key_prefix` data source](https://registry.terraform.io/providers/hashicorp/consul/latest/docs/data-sources/key_prefix) | | HashiCorp Terraform Cloud | Normal `outputs` terraform block | [`tfe_outputs` data source](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/data-sources/outputs) | | Kubernetes | [`kubernetes_config_map` resource type](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/config_map) | [`kubernetes_config_map` data source](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/data-sources/config_map) | | OCI Object Storage | [`oci_objectstorage_bucket` resource type](https://registry.terraform.io/providers/hashicorp/oci/latest/docs/resources/objectstorage_object) | [`oci_objectstorage_bucket` data source](https://registry.terraform.io/providers/hashicorp/oci/latest/docs/data-sources/objectstorage_object) | Note These are some common options from the Official OpenTofu providers, but there are too many configuration storage options for us to list them all here, including some in partner and community providers. Any pair of managed resource type and corresponding data source can potentially be used to share data between OpenTofu configurations. See individual provider documentation to find other possibilities. A key advantage of using a separate explicit configuration store instead of `terraform_remote_state` is that the data can potentially also be read by systems other than OpenTofu, such as configuration management or scheduler systems within your compute instances. For that reason, we recommend selecting a configuration store that your other infrastructure could potentially make use of. For example: * If you wish to share IP addresses and hostnames, you could publish them as normal DNS `A`, `AAAA`, `CNAME`, and `SRV` records in a private DNS zone and then configure your other infrastructure to refer to that zone so you can find infrastructure objects via your system's built-in DNS resolver. * If you use HashiCorp Consul then publishing data to the Consul key/value store or Consul service catalog can make that data also accessible via [Consul Template](https://github.com/hashicorp/consul-template) or the [HashiCorp Nomad](https://developer.hashicorp.com/nomad/docs/job-specification/template) `template` stanza. * If you use Kubernetes then you can [make Config Maps available to your Pods](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/) . Some of the data stores listed above are specifically designed for storing small configuration values, while others are generic blob storage systems. For those generic systems, you can use [the `jsonencode` function](https://opentofu.org/docs/v1.10/language/functions/jsonencode/) and [the `jsondecode` function](https://opentofu.org/docs/v1.10/language/functions/jsondecode/) respectively to store and retrieve structured data. You can encapsulate the implementation details of retrieving your published configuration data by writing a [data-only module](https://opentofu.org/docs/v1.10/language/modules/develop/composition/#data-only-modules) containing the necessary data source configuration and any necessary post-processing such as JSON decoding. You can then change that module later if you switch to a different strategy for sharing data between multiple OpenTofu configurations. Example Usage (`remote` Backend)[​](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#example-usage-remote-backend "Direct link to example-usage-remote-backend") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block data "terraform_remote_state" "vpc" { backend = "remote" config = { organization = "hashicorp" workspaces = { name = "vpc-prod" } }}resource "aws_instance" "foo" { # ... subnet_id = data.terraform_remote_state.vpc.outputs.subnet_id} Example Usage (`local` Backend)[​](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#example-usage-local-backend "Direct link to example-usage-local-backend") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Block data "terraform_remote_state" "vpc" { backend = "local" config = { path = "..." }}resource "aws_instance" "foo" { # ... subnet_id = data.terraform_remote_state.vpc.outputs.subnet_id} Argument Reference[​](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#argument-reference "Direct link to Argument Reference") ------------------------------------------------------------------------------------------------------------------------------------------------ The following arguments are supported: * `backend` - (Required) The remote backend to use. * `workspace` - (Optional) The OpenTofu workspace to use, if the backend supports workspaces. * `config` - (Optional; object) The configuration of the remote backend. Although this argument is listed as optional, most backends require some configuration. The `config` object can use any arguments that would be valid in the equivalent `terraform { backend "" { ... } }` block. See [the documentation of your chosen backend](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/) for details. Note If the backend configuration requires a nested block, specify it here as a normal attribute with an object value. (For example, `workspaces = { ... }` instead of `workspaces { ... }`.) * `defaults` - (Optional; object) Default values for outputs, in case the state file is empty or lacks a required output. Attributes Reference[​](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#attributes-reference "Direct link to Attributes Reference") ------------------------------------------------------------------------------------------------------------------------------------------------------ In addition to the above, the following attributes are exported: * `outputs` - An object containing every root-level [output](https://opentofu.org/docs/v1.10/language/values/outputs/) in the remote state. Root Outputs Only[​](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#root-outputs-only "Direct link to Root Outputs Only") --------------------------------------------------------------------------------------------------------------------------------------------- Only the root-level output values from the remote state snapshot are exposed for use elsewhere in your module. Resource data and output values from nested modules are not accessible. If you wish to make a nested module output value accessible as a root module output value, you must explicitly configure a passthrough in the root module. For example: For example: Code Block module "app" { source = "..."}output "app_value" { value = module.app.example} In this example, the output value named `example` from the "app" module is available as the `app_value` root module output value. If this configuration didn't include the `output "app_value"` block then the data would not be accessible via `terraform_remote_state`. Warning Although `terraform_remote_state` doesn't expose any other state snapshot information for use in configuration, the state snapshot data is a single object and so any user or server which has enough access to read the root module output values will also always have access to the full state snapshot data by direct network requests. Don't use `terraform_remote_state` if any of the resources in your configuration work with data that you consider sensitive. * [Alternative Ways to Share Data Between Configurations](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#alternative-ways-to-share-data-between-configurations) * [Example Usage (`remote` Backend)](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#example-usage-remote-backend) * [Example Usage (`local` Backend)](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#example-usage-local-backend) * [Argument Reference](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#argument-reference) * [Attributes Reference](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#attributes-reference) * [Root Outputs Only](https://opentofu.org/docs/v1.10/language/state/remote-state-data/#root-outputs-only) --- # Resource Addressing | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Resource Addressing =================== A _resource address_ is a string that identifies zero or more resource instances in your overall configuration. An address is made up of two parts: Code Block [module path][resource spec] In some contexts OpenTofu might allow for an incomplete resource address that only refers to a module as a whole, or that omits the index for a multi-instance resource. In those cases, the meaning depends on the context, so you'll need to refer to the documentation for the specific feature you are using which parses resource addresses. Module path[​](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#module-path "Direct link to Module path") ------------------------------------------------------------------------------------------------------------------------ A module path addresses a module within the tree of modules. It takes the form: Code Block module.module_name[module index] * `module` - Module keyword indicating a child module (non-root). Multiple `module` keywords in a path indicate nesting. * `module_name` - User-defined name of the module. * `[module index]` - (Optional) [Index](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#index-values-for-modules-and-resources) to select an instance from a module call that has multiple instances, surrounded by square bracket characters (`[` and `]`). An address without a resource spec, i.e. `module.foo` applies to every resource within the module if a single module, or all instances of a module if a module has multiple instances. To address all resources of a particular module instance, include the module index in the address, such as `module.foo[0]`. If the module path is omitted, the address applies to the root module. An example of the `module` keyword delineating between two modules that have multiple instances: Code Block module.foo[0].module.bar["a"] Resource spec[​](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#resource-spec "Direct link to Resource spec") ------------------------------------------------------------------------------------------------------------------------------ A resource spec addresses a specific resource instance in the selected module. It has the following syntax: Code Block resource_type.resource_name[instance index] * `resource_type` - Type of the resource being addressed. * `resource_name` - User-defined name of the resource. * `[instance index]` - (Optional) [Index](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#index-values-for-modules-and-resources) to select an instance from a resource that has multiple instances, surrounded by square bracket characters (`[` and `]`). A resource spec without a module path prefix matches only resources in the root module. Index values for Modules and Resources[​](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#index-values-for-modules-and-resources "Direct link to Index values for Modules and Resources") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The following specifications apply to index values on modules and resources with multiple instances: * `[N]` where `N` is a `0`\-based numerical index into a resource with multiple instances specified by the `count` meta-argument. Omitting an index when addressing a resource where `count > 1` means that the address references all instances. * `["INDEX"]` where `INDEX` is a alphanumerical key index into a resource with multiple instances specified by the `for_each` meta-argument. Examples[​](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#examples "Direct link to Examples") --------------------------------------------------------------------------------------------------------------- ### count Example[​](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#count-example "Direct link to count Example") Given a OpenTofu config that includes: Code Block resource "aws_instance" "web" { # ... count = 4} An address like this: Code Block aws_instance.web[3] Refers to only the last instance in the config, and an address like this: Code Block aws_instance.web Refers to all four "web" instances. ### for\_each Example[​](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#for_each-example "Direct link to for_each Example") Given a OpenTofu config that includes: Code Block resource "aws_instance" "web" { # ... for_each = { "tofu": "value1", "resource": "value2", "indexing": "value3", "example": "value4", }} An address like this: Code Block aws_instance.web["example"] Refers to only the "example" instance in the config, and resolves to "value4". Resource Addresses on the Command Line[​](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#resource-addresses-on-the-command-line "Direct link to Resource Addresses on the Command Line") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When using resource addresses directly in command line arguments such as the `-target`, `-exclude`, and `-replace` planning options, the punctuation characters in the resource address syntax might conflict with special interpretation of those characters by the shell you are using to run OpenTofu. To avoid this, you must ensure that those characters are properly quoted or escaped so that your shell will pass them literally to OpenTofu. The syntax for doing so varies depending on your shell or command interpreter: * For Unix-style shells such as `bash`, write the resource address in single quotes (`'`): Code Block tofu apply -target='aws_instance.example["foo"]' If you need to specify an instance key string that includes a single quote character, use two separate single-quoted sequences with an escaped single quote between them. For example, the following includes the instance key `"example'foo"`: Code Block tofu apply -target='aws_instance.example["example'\''foo"]' * For PowerShell 7.3 or later, write the resource address in single quotes (`'`): Code Block tofu apply -target='aws_instance.example["foo"]' Older versions of PowerShell have different requirements. For more information, refer to [Passing arguments that contain quote characters](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing?view=powershell-7.5#passing-arguments-that-contain-quote-characters) . If you need to specify an instance key string that includes a single quote character, use two consecutive single quotes to represent a single literal quote. For example, the following includes the instance key `"example'foo"`: Code Block tofu apply -target='aws_instance.example["example''foo"]' * For Windows Command Prompt (`cmd.exe`), write the resource address in double quotes (`"`) and escape any quotes from the resource address using a backslash (`\`): Code Block tofu apply -target="aws_instance.example[\"foo\"]" Resource Addresses in Targeting Files[​](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#resource-addresses-in-targeting-files "Direct link to Resource Addresses in Targeting Files") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ The `-target-file` and `-exclude-file` [planning options](https://opentofu.org/docs/v1.11/cli/commands/plan/#planning-options) read resource addresses from a separate file that can contain zero or more resource addresses. OpenTofu interprets a targeting file on a line-by-line basis. The content of each line must be one of the following: * A resource address using the syntax described above, in which case OpenTofu adds the address to the set of target addresses. * A comment starting with the `#` character, in which case OpenTofu ignores the line completely. * A blank line consisting only of zero or more space characters, in which case OpenTofu also ignores the line completely. For example, the following is a valid targeting file specifying a number of resource addresses that might need to be created first when applying a certain configuration for the first time: Code Block # These modules must be targeted during initial creation.module.networkmodule.cluster# The following resources must also be included on initial# creation.aws_iam_role.all["base"]aws_iam_role_policy.all["base"] The targeting file above would match all instances of all resources whose addresses begin with `module.network` or `module.cluster`, and also the specific resource instances `aws_iam_role.all["base"]` and `aws_iam_role_policy.all["base"]`. * [Module path](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#module-path) * [Resource spec](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#resource-spec) * [Index values for Modules and Resources](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#index-values-for-modules-and-resources) * [Examples](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#examples) * [count Example](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#count-example) * [for\_each Example](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#for_each-example) * [Resource Addresses on the Command Line](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#resource-addresses-on-the-command-line) * [Resource Addresses in Targeting Files](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/#resource-addresses-in-targeting-files) --- # Building a Docker Image with OpenTofu | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/install/docker/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Building a Docker Image with OpenTofu ===================================== Important Change Previously, OpenTofu provided official Docker images that could be used directly. Starting with OpenTofu 1.10, direct usage of the official images is no longer supported. This page now focuses on how to build your own Docker image with OpenTofu included. If you were previously using `docker run ghcr.io/opentofu/opentofu`, you will need to build your own image following the instructions below. Building your own image[​](https://opentofu.org/docs/v1.11/intro/install/docker/#building-your-own-image "Direct link to Building your own image") --------------------------------------------------------------------------------------------------------------------------------------------------- If you need OpenTofu in a Docker container, you will need to build your own image. You can do this in two ways: 1. Use a multi-stage build to copy the `tofu` binary from the minimal OpenTofu image to your image. 2. Use the standalone installation script to install `tofu` into your container image. ### Method 1: Using a multi-stage build[​](https://opentofu.org/docs/v1.11/intro/install/docker/#method-1-using-a-multi-stage-build "Direct link to Method 1: Using a multi-stage build") The minimal OpenTofu images contain only the `tofu` binary at `/usr/local/bin/tofu`. You can use these images in a multi-stage build to copy the binary into your own image. Available minimal image tags: * `ghcr.io/opentofu/opentofu:minimal` - Latest version * `ghcr.io/opentofu/opentofu:1-minimal` - Latest 1.x version * `ghcr.io/opentofu/opentofu:1.9-minimal` - Latest 1.9.x version * `ghcr.io/opentofu/opentofu:1.9.1-minimal` - Specific version Example `Dockerfile` using Alpine Linux: Code Block FROM ghcr.io/opentofu/opentofu:minimal AS tofuFROM alpine:3.20# Copy the tofu binary from the minimal imageCOPY --from=tofu /usr/local/bin/tofu /usr/local/bin/tofu# Add any other tools or dependencies you needRUN apk add --no-cache git curl# Your application setupWORKDIR /workspace Example using Ubuntu: Code Block FROM ghcr.io/opentofu/opentofu:minimal AS tofuFROM ubuntu:24.04# Copy the tofu binaryCOPY --from=tofu /usr/local/bin/tofu /usr/local/bin/tofu# Install dependenciesRUN apt-get update && apt-get install -y \ git \ curl \ && rm -rf /var/lib/apt/lists/*WORKDIR /workspace ### Method 2: Using the installation script[​](https://opentofu.org/docs/v1.11/intro/install/docker/#method-2-using-the-installation-script "Direct link to Method 2: Using the installation script") You can also use the OpenTofu installation script to install the binary directly in your container image. #### Step 1: Download the installation script[​](https://opentofu.org/docs/v1.11/intro/install/docker/#step-1-download-the-installation-script "Direct link to Step 1: Download the installation script") First, download the installation script following the [standalone installation instructions](https://opentofu.org/docs/v1.11/intro/install/standalone/) and place it next to your `Dockerfile`. #### Step 2: Install OpenTofu in your image[​](https://opentofu.org/docs/v1.11/intro/install/docker/#step-2-install-opentofu-in-your-image "Direct link to Step 2: Install OpenTofu in your image") Example `Dockerfile` using the installation script: Code Block FROM alpine:3.20# Copy the installation scriptCOPY install-opentofu.sh /tmp/install-opentofu.sh# Install dependencies needed for the scriptRUN apk add --no-cache bash curl gpg gpg-agent# Run the installation scriptRUN chmod +x /tmp/install-opentofu.sh && \ /tmp/install-opentofu.sh --install-method standalone --install-path /usr/local/bin && \ rm /tmp/install-opentofu.sh# Add your other dependenciesRUN apk add --no-cache gitWORKDIR /workspace For Ubuntu-based images: Code Block FROM ubuntu:24.04# Copy the installation scriptCOPY install-opentofu.sh /tmp/install-opentofu.sh# Install dependenciesRUN apt-get update && apt-get install -y \ curl \ gpg \ && rm -rf /var/lib/apt/lists/*# Run the installation scriptRUN chmod +x /tmp/install-opentofu.sh && \ /tmp/install-opentofu.sh --install-method standalone --install-path /usr/local/bin && \ rm /tmp/install-opentofu.sh# Add your other dependenciesRUN apt-get update && apt-get install -y \ git \ && rm -rf /var/lib/apt/lists/*WORKDIR /workspace Verifying your image[​](https://opentofu.org/docs/v1.11/intro/install/docker/#verifying-your-image "Direct link to Verifying your image") ------------------------------------------------------------------------------------------------------------------------------------------ After building your image, verify that OpenTofu is correctly installed: Code Block docker build -t my-opentofu-image .docker run --rm my-opentofu-image tofu --version * [Building your own image](https://opentofu.org/docs/v1.11/intro/install/docker/#building-your-own-image) * [Method 1: Using a multi-stage build](https://opentofu.org/docs/v1.11/intro/install/docker/#method-1-using-a-multi-stage-build) * [Method 2: Using the installation script](https://opentofu.org/docs/v1.11/intro/install/docker/#method-2-using-the-installation-script) * [Verifying your image](https://opentofu.org/docs/v1.11/intro/install/docker/#verifying-your-image) --- # Installing OpenTofu on RHEL, openSUSE, AlmaLinux and other RPM-based distributions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/install/rpm/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Installing OpenTofu on RHEL, openSUSE, AlmaLinux and other RPM-based distributions ================================================================================== [Thank you to Buildkite for sponsoring the OpenTofu package hosting.](https://buildkite.com/) You can install OpenTofu from our RPM repository by following the step-by-step instructions below. Installing using the installer[​](https://opentofu.org/docs/v1.11/intro/install/rpm/#installing-using-the-installer "Direct link to Installing using the installer") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can use the OpenTofu installer script to run the installation. Code Block # Download the installer script:curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh -o install-opentofu.sh# Alternatively: wget --secure-protocol=TLSv1_2 --https-only https://get.opentofu.org/install-opentofu.sh -O install-opentofu.sh# Give it execution permissions:chmod +x install-opentofu.sh# Please inspect the downloaded script# Run the installer:./install-opentofu.sh --install-method rpm# Remove the installer:rm -f install-opentofu.sh Step-by-step instructions[​](https://opentofu.org/docs/v1.11/intro/install/rpm/#step-by-step-instructions "Direct link to Step-by-step instructions") ------------------------------------------------------------------------------------------------------------------------------------------------------ The following steps explain how to set up the OpenTofu RPM repositories. These instructions should work on most RPM-based Linux systems. ### Adding the OpenTofu repository[​](https://opentofu.org/docs/v1.11/intro/install/rpm/#adding-the-opentofu-repository "Direct link to Adding the OpenTofu repository") * Yum (RHEL/AlmaLinux/etc.) * Zypper (openSUSE) Create the `/etc/yum.repos.d/opentofu.repo` file by running the following command: Code Block cat >/etc/yum.repos.d/opentofu.repo </etc/zypp/repos.d/opentofu.repo < [registry] example.com/opentofu-providers/hashicorp/tls:4.0.6Digest: sha256:da13ebaa32ba856d75da18e38daabc7a65ac8853230dfcc817f8ccbac15b639a ORAS copies everything that the local 4.0.6 tag refers to into the remote registry, and then creates a remote tag 4.0.6 referring to the same content. This provider is now available for use using an `oci_mirror` installation block configured as in the example at the start of this page. * [`oci_mirror` installation method arguments](https://opentofu.org/docs/v1.11/cli/oci_registries/provider-mirror/#oci_mirror-installation-method-arguments) * [Required OCI Repository Content](https://opentofu.org/docs/v1.11/cli/oci_registries/provider-mirror/#required-oci-repository-content) * [Tag Names](https://opentofu.org/docs/v1.11/cli/oci_registries/provider-mirror/#tag-names) * [Manifest Structure](https://opentofu.org/docs/v1.11/cli/oci_registries/provider-mirror/#manifest-structure) * [Assembling and Pushing Provider Manifests](https://opentofu.org/docs/v1.11/cli/oci_registries/provider-mirror/#assembling-and-pushing-provider-manifests) * [Install and Configure ORAS](https://opentofu.org/docs/v1.11/cli/oci_registries/provider-mirror/#install-and-configure-oras) * [Local OCI Image Layout](https://opentofu.org/docs/v1.11/cli/oci_registries/provider-mirror/#local-oci-image-layout) * [Single-platform Image Manifests](https://opentofu.org/docs/v1.11/cli/oci_registries/provider-mirror/#single-platform-image-manifests) * [Multi-platform Index Manifest](https://opentofu.org/docs/v1.11/cli/oci_registries/provider-mirror/#multi-platform-index-manifest) * [Push the Artifacts to a Remote Repository](https://opentofu.org/docs/v1.11/cli/oci_registries/provider-mirror/#push-the-artifacts-to-a-remote-repository) --- # Input Variables | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/values/variables/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Input Variables =============== Input variables let you customize aspects of modules without altering the module's own source code. This functionality allows you to share modules across different OpenTofu configurations, making your module composable and reusable. When you declare variables in the root module of your configuration, you can set their values using CLI options and environment variables. When you declare them in [child modules](https://opentofu.org/docs/v1.10/language/modules/) , the calling module should pass values in the `module` block. If you're familiar with traditional programming languages, it can be useful to compare modules to function definitions: * Input variables are like function arguments. * [Output values](https://opentofu.org/docs/v1.10/language/values/outputs/) are like function return values. * [Local values](https://opentofu.org/docs/v1.10/language/values/locals/) are like a function's temporary local variables. Note For brevity, input variables are often referred to as just "variables" or "OpenTofu variables" when it is clear from context what sort of variable is being discussed. Other kinds of variables in OpenTofu include _environment variables_ (set by the shell where OpenTofu runs) and _expression variables_ (used to indirectly represent a value in an [expression](https://opentofu.org/docs/v1.10/language/expressions/) ). Declaring an Input Variable[​](https://opentofu.org/docs/v1.10/language/values/variables/#declaring-an-input-variable "Direct link to Declaring an Input Variable") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- Each input variable accepted by a module must be declared using a `variable` block: Code Block variable "image_id" { type = string}variable "availability_zone_names" { type = list(string) default = ["us-west-1a"]}variable "docker_ports" { type = list(object({ internal = number external = number protocol = string })) default = [ { internal = 8300 external = 8300 protocol = "tcp" } ]} The label after the `variable` keyword is a name for the variable, which must be unique among all variables in the same module. This name is used to assign a value to the variable from outside and to reference the variable's value from within the module. The name of a variable can be any valid [identifier](https://opentofu.org/docs/v1.10/language/syntax/configuration/#identifiers) _except_ the following: `source`, `version`, `providers`, `count`, `for_each`, `lifecycle`, `depends_on`, `locals`. These names are reserved for meta-arguments in [module configuration blocks](https://opentofu.org/docs/v1.10/language/modules/syntax/) , and cannot be declared as variable names. Arguments[​](https://opentofu.org/docs/v1.10/language/values/variables/#arguments "Direct link to Arguments") -------------------------------------------------------------------------------------------------------------- OpenTofu CLI defines the following optional arguments for variable declarations: * [`default`](https://opentofu.org/docs/v1.10/language/values/variables/#default-values) - A default value which then makes the variable optional. * [`type`](https://opentofu.org/docs/v1.10/language/values/variables/#type-constraints) - This argument specifies what value types are accepted for the variable. * [`description`](https://opentofu.org/docs/v1.10/language/values/variables/#input-variable-documentation) - This specifies the input variable's documentation. * [`validation`](https://opentofu.org/docs/v1.10/language/values/variables/#custom-validation-rules) - A block to define validation rules, usually in addition to type constraints. * [`sensitive`](https://opentofu.org/docs/v1.10/language/values/variables/#suppressing-values-in-cli-output) - Limits OpenTofu UI output when the variable is used in configuration. * [`nullable`](https://opentofu.org/docs/v1.10/language/values/variables/#disallowing-null-input-values) - Specify if the variable can be `null` within the module. * [`deprecated`](https://opentofu.org/docs/v1.10/language/values/variables/#marking-variable-as-deprecated) - Mark the variable as deprecated to warn callers about migration. ### Default values[​](https://opentofu.org/docs/v1.10/language/values/variables/#default-values "Direct link to Default values") The variable declaration can also include a `default` argument. If present, the variable is considered to be _optional_ and the default value will be used if no value is set when calling the module or running OpenTofu. The `default` argument requires a literal value and cannot reference other objects in the configuration. ### Type Constraints[​](https://opentofu.org/docs/v1.10/language/values/variables/#type-constraints "Direct link to Type Constraints") The `type` argument in a `variable` block allows you to restrict the [type of value](https://opentofu.org/docs/v1.10/language/expressions/types/) that will be accepted as the value for a variable. If no type constraint is set then a value of any type is accepted. While type constraints are optional, we recommend specifying them; they can serve as helpful reminders for users of the module, and they allow OpenTofu to return a helpful error message if the wrong type is used. Type constraints are created from a mixture of type keywords and type constructors. The supported type keywords are: * `string` * `number` * `bool` The type constructors allow you to specify complex types such as collections: * `list()` * `set()` * `map()` * `object({ = , ... })` * `tuple([, ...])` The keyword `any` may be used to indicate that any type is acceptable. For more information on the meaning and behavior of these different types, as well as detailed information about automatic conversion of complex types, see [Type Constraints](https://opentofu.org/docs/v1.10/language/expressions/types/) . If both the `type` and `default` arguments are specified, the given default value must be convertible to the specified type. ### Input Variable Documentation[​](https://opentofu.org/docs/v1.10/language/values/variables/#input-variable-documentation "Direct link to Input Variable Documentation") Because the input variables of a module are part of its user interface, you can briefly describe the purpose of each variable using the optional `description` argument: Code Block variable "image_id" { type = string description = "The id of the machine image (AMI) to use for the server."} The description should concisely explain the purpose of the variable and what kind of value is expected. This description string might be included in documentation about the module, and so it should be written from the perspective of the user of the module rather than its maintainer. For commentary for module maintainers, use comments. ### Custom Validation Rules[​](https://opentofu.org/docs/v1.10/language/values/variables/#custom-validation-rules "Direct link to Custom Validation Rules") You can specify custom validation rules for a particular variable by adding a `validation` block within the corresponding `variable` block. The example below checks whether the AMI ID has the correct syntax. Code Block variable "image_id" { type = string description = "The id of the machine image (AMI) to use for the server." validation { condition = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-" error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"." }} Refer to [Custom Condition Checks](https://opentofu.org/docs/v1.10/language/expressions/custom-conditions/#input-variable-validation) for more details. ### Suppressing Values in CLI Output[​](https://opentofu.org/docs/v1.10/language/values/variables/#suppressing-values-in-cli-output "Direct link to Suppressing Values in CLI Output") Setting a variable as `sensitive` prevents OpenTofu from showing its value in the `plan` or `apply` output, when you use that variable elsewhere in your configuration. OpenTofu will still record sensitive values in the [state](https://opentofu.org/docs/v1.10/language/state/) , and so anyone who can access the state data will have access to the sensitive values in cleartext. For more information, see [_Sensitive Data in State_](https://opentofu.org/docs/v1.10/language/state/sensitive-data/) . Declare a variable as sensitive by setting the `sensitive` argument to `true`: Code Block variable "user_information" { type = object({ name = string address = string }) sensitive = true}resource "some_resource" "a" { name = var.user_information.name address = var.user_information.address} Any expressions whose result depends on the sensitive variable will be treated as sensitive themselves, and so in the above example the two arguments of `resource "some_resource" "a"` will also be hidden in the plan output: Code Block OpenTofu will perform the following actions: # some_resource.a will be created + resource "some_resource" "a" { + name = (sensitive value) + address = (sensitive value) }Plan: 1 to add, 0 to change, 0 to destroy. In some cases where you use a sensitive variable inside a nested block, OpenTofu may treat the entire block as redacted. This happens for resource types where all of the blocks of a particular type are required to be unique, and so disclosing the content of one block might imply the content of a sibling block. Code Block # some_resource.a will be updated in-place ~ resource "some_resource" "a" { ~ nested_block { # At least one attribute in this block is (or was) sensitive, # so its contents will not be displayed. } } A provider can also [declare an attribute as sensitive](https://developer.hashicorp.com/terraform/plugin/best-practices/sensitive-state#using-sensitive-flag-functionality) , which will cause OpenTofu to hide it from regular output regardless of how you assign it a value. For more information, see [Sensitive Resource Attributes](https://opentofu.org/docs/v1.10/language/expressions/references/#sensitive-resource-attributes) . If you use a sensitive value as part of an [output value](https://opentofu.org/docs/v1.10/language/values/outputs/) then OpenTofu will require you to also mark the output value itself as sensitive, to confirm that you intended to export it. #### Cases where OpenTofu may disclose a sensitive variable[​](https://opentofu.org/docs/v1.10/language/values/variables/#cases-where-opentofu-may-disclose-a-sensitive-variable "Direct link to Cases where OpenTofu may disclose a sensitive variable") A `sensitive` variable is a configuration-centered concept, and values are sent to providers without any obfuscation. A provider error could disclose a value if that value is included in the error message. For example, a provider might return the following error even if "foo" is a sensitive value: `"Invalid value 'foo' for field"` If a resource attribute is used as, or part of, the provider-defined resource id, an `apply` will disclose the value. In the example below, the `prefix` attribute has been set to a sensitive variable, but then that value ("jae") is later disclosed as part of the resource id: Code Block # random_pet.animal will be created + resource "random_pet" "animal" { + id = (known after apply) + length = 2 + prefix = (sensitive value) + separator = "-" }Plan: 1 to add, 0 to change, 0 to destroy....random_pet.animal: Creating...random_pet.animal: Creation complete after 0s [id=jae-known-mongoose] ### Disallowing Null Input Values[​](https://opentofu.org/docs/v1.10/language/values/variables/#disallowing-null-input-values "Direct link to Disallowing Null Input Values") The `nullable` argument in a variable block controls whether the module caller may assign the value `null` to the variable. Code Block variable "example" { type = string nullable = false} The default value for `nullable` is `true`. When `nullable` is `true`, `null` is a valid value for the variable, and the module configuration must always account for the possibility of the variable value being `null`. Passing a `null` value as a module input argument will override any `default` value. Setting `nullable` to `false` ensures that the variable value will never be `null` within the module. If `nullable` is `false` and the variable has a `default` value, then OpenTofu uses the default when a module input argument is `null`. The `nullable` argument only controls where the direct value of the variable may be `null`. For variables of collection or structural types, such as lists or objects, the caller may still use `null` in nested elements or attributes, as long as the collection or structure itself is not null. ### Marking variable as deprecated[​](https://opentofu.org/docs/v1.10/language/values/variables/#marking-variable-as-deprecated "Direct link to Marking variable as deprecated") Warning This feature is considered experimental and the final UX may change in the future. The `deprecated` argument in a variable block indicates its deprecation and potential removal in the future. This attribute should contain non-empty string and should provide instructions on how to migrate away from usage of this variable. Here is an example of the configuration: Code Block variable "examle" { type = string deprecated = "'examle' variable must no longer be used due to a typo, use 'example' instead"} The caller of the module will receive a warning if the deprecated variable is used in their configuration: Code Block β”‚ Warning: Variable marked as deprecated by the module authorβ”‚β”‚ on main.tf line 3, in module "mod":β”‚ 3: examle = "a"β”‚β”‚ Variable "examle" is marked as deprecated with the following message:β”‚ 'examle' variable must no longer be used due to a typo, use 'example' instead Deprecation warnings can be filtered or disabled by using the `-deprecation` CLI argument. For more details, check its description in the command options for [plan](https://opentofu.org/docs/v1.10/cli/commands/plan/#other-options) and [apply](https://opentofu.org/docs/v1.10/cli/commands/apply/#apply-options) . Using Input Variable Values[​](https://opentofu.org/docs/v1.10/language/values/variables/#using-input-variable-values "Direct link to Using Input Variable Values") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- Within the module that declared a variable, its value can be accessed from within [expressions](https://opentofu.org/docs/v1.10/language/expressions/) as `var.`, where `` matches the label given in the declaration block: Note Input variables are _created_ by a `variable` block, but you _reference_ them as attributes on an object named `var`. Code Block resource "aws_instance" "example" { instance_type = "t2.micro" ami = var.image_id} The value assigned to a variable can only be accessed in expressions within the module where it was declared. Assigning Values to Root Module Variables[​](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables "Direct link to Assigning Values to Root Module Variables") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When variables are declared in the root module of your configuration, they can be set in a number of ways: * Individually, with the `-var` command line option. * In variable definitions (`.tfvars`) files, either specified on the command line or automatically loaded. * As environment variables. The following sections describe these options in more detail. This section does not apply to _child_ modules, where values for input variables are instead assigned in the configuration of their parent module, as described in [_Modules_](https://opentofu.org/docs/v1.10/language/modules/) . ### Variables on the Command Line[​](https://opentofu.org/docs/v1.10/language/values/variables/#variables-on-the-command-line "Direct link to Variables on the Command Line") To specify individual variables on the command line, use the `-var` option when running the `tofu plan` and `tofu apply` commands: Code Block tofu apply -var="image_id=ami-abc123"tofu apply -var='image_id_list=["ami-abc123","ami-def456"]' -var="instance_type=t2.micro"tofu apply -var='image_id_map={"us-east-1":"ami-abc123","us-east-2":"ami-def456"}' The above examples show appropriate syntax for Unix-style shells, such as on Linux or macOS. For more information on shell quoting, including additional examples for Windows Command Prompt, see [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) . You can use the `-var` option multiple times in a single command to set several different variables. ### Variable Definitions (`.tfvars`) Files[​](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files "Direct link to variable-definitions-tfvars-files") To set lots of variables, it is more convenient to specify their values in a _variable definitions file_ (with a filename ending in either `.tfvars` or `.tfvars.json`) and then specify that file on the command line with `-var-file`: Code Block tofu apply -var-file="testing.tfvars" A variable definitions file uses the same basic syntax as OpenTofu language files, but consists only of variable name assignments: Code Block image_id = "ami-abc123"availability_zone_names = [ "us-east-1a", "us-west-1c",] OpenTofu also automatically loads a number of variable definitions files if they are present: * Files named exactly `terraform.tfvars` or `terraform.tfvars.json`. * Any files with names ending in `.auto.tfvars` or `.auto.tfvars.json`. Files whose names end with `.json` are parsed instead as JSON objects, with the root object properties corresponding to variable names: Code Block { "image_id": "ami-abc123", "availability_zone_names": ["us-west-1a", "us-west-1c"]} ### Environment Variables[​](https://opentofu.org/docs/v1.10/language/values/variables/#environment-variables "Direct link to Environment Variables") As a fallback for the other ways of defining variables, OpenTofu searches the environment of its own process for environment variables named `TF_VAR_` followed by the name of a declared variable. This can be useful when running OpenTofu in automation, or when running a sequence of OpenTofu commands in succession with the same variables. For example, at a `bash` prompt on a Unix system: Code Block $ export TF_VAR_image_id=ami-abc123$ tofu plan... On operating systems where environment variable names are case-sensitive, OpenTofu matches the variable name exactly as given in configuration, and so the required environment variable name will usually have a mix of upper and lower case letters as in the above example. ### Complex-typed Values[​](https://opentofu.org/docs/v1.10/language/values/variables/#complex-typed-values "Direct link to Complex-typed Values") When variable values are provided in a variable definitions file, you can use OpenTofu's usual syntax for [literal expressions](https://opentofu.org/docs/v1.10/language/expressions/types/#literal-expressions) to assign complex-typed values, like lists and maps. Some special rules apply to the `-var` command line option and to environment variables. For convenience, OpenTofu defaults to interpreting `-var` and environment variable values as literal strings, which need only shell quoting, and no special quoting for OpenTofu. For example, in a Unix-style shell: Code Block $ export TF_VAR_image_id='ami-abc123' However, if a root module variable uses a [type constraint](https://opentofu.org/docs/v1.10/language/values/variables/#type-constraints) to require a complex value (list, set, map, object, or tuple), OpenTofu will instead attempt to parse its value using the same syntax used within variable definitions files, which requires careful attention to the string escaping rules in your shell: Code Block $ export TF_VAR_availability_zone_names='["us-west-1b","us-west-1d"]' For readability, and to avoid the need to worry about shell escaping, we recommend always setting complex variable values via variable definitions files. For more information on quoting and escaping for `-var` arguments, see [Input Variables on the Command Line](https://opentofu.org/docs/v1.10/cli/commands/plan/#input-variables-on-the-command-line) . ### Values for Undeclared Variables[​](https://opentofu.org/docs/v1.10/language/values/variables/#values-for-undeclared-variables "Direct link to Values for Undeclared Variables") If you have defined a variable value, but not its corresponding `variable {}` definition, you may get an error or warning depending on how you have provided that value. If you provide values for undeclared variables defined as [environment variables](https://opentofu.org/docs/v1.10/language/values/variables/#environment-variables) you will not get an error or warning. This is because environment variables may be declared but not used in all configurations that might be run. If you provide values for undeclared variables defined [in a file](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) you will get a warning. This is to help in cases where you have provided a variable value _meant_ for a variable declaration, but perhaps there is a mistake in the value definition. For example, the following configuration: Code Block variable "moose" { type = string} And the following `.tfvars` file: Code Block mosse = "Moose" Will cause OpenTofu to warn you that there is no variable declared `"mosse"`, which can help you spot this mistake. If you use `.tfvars` files across multiple configurations and expect to continue to see this warning, you can use the [`-compact-warnings`](https://opentofu.org/docs/v1.10/cli/commands/plan/#compact-warnings) option to simplify your output. If you provide values for undeclared variables on the [command line](https://opentofu.org/docs/v1.10/language/values/variables/#variables-on-the-command-line) , OpenTofu will return an error. To avoid this error, either declare a variable block for the value, or remove the variable value from your OpenTofu call. ### Variable Definition Precedence[​](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definition-precedence "Direct link to Variable Definition Precedence") The above mechanisms for setting variables can be used together in any combination. If the same variable is assigned multiple values, OpenTofu uses the _last_ value it finds, overriding any previous values. Note that the same variable cannot be assigned multiple values within a single source. OpenTofu loads variables in the following order, with later sources taking precedence over earlier ones: * Environment variables * The `terraform.tfvars` file, if present. * The `terraform.tfvars.json` file, if present. * Any `*.auto.tfvars` or `*.auto.tfvars.json` files, processed in lexical order of their filenames. * Any `-var` and `-var-file` options on the command line, in the order they are provided. Important Variables with map and object values behave the same way as other variables: the last value found overrides the previous values. This is a change from previous versions of OpenTofu, which would _merge_ map values instead of overriding them. * [Declaring an Input Variable](https://opentofu.org/docs/v1.10/language/values/variables/#declaring-an-input-variable) * [Arguments](https://opentofu.org/docs/v1.10/language/values/variables/#arguments) * [Default values](https://opentofu.org/docs/v1.10/language/values/variables/#default-values) * [Type Constraints](https://opentofu.org/docs/v1.10/language/values/variables/#type-constraints) * [Input Variable Documentation](https://opentofu.org/docs/v1.10/language/values/variables/#input-variable-documentation) * [Custom Validation Rules](https://opentofu.org/docs/v1.10/language/values/variables/#custom-validation-rules) * [Suppressing Values in CLI Output](https://opentofu.org/docs/v1.10/language/values/variables/#suppressing-values-in-cli-output) * [Disallowing Null Input Values](https://opentofu.org/docs/v1.10/language/values/variables/#disallowing-null-input-values) * [Marking variable as deprecated](https://opentofu.org/docs/v1.10/language/values/variables/#marking-variable-as-deprecated) * [Using Input Variable Values](https://opentofu.org/docs/v1.10/language/values/variables/#using-input-variable-values) * [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.10/language/values/variables/#assigning-values-to-root-module-variables) * [Variables on the Command Line](https://opentofu.org/docs/v1.10/language/values/variables/#variables-on-the-command-line) * [Variable Definitions (`.tfvars`) Files](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definitions-tfvars-files) * [Environment Variables](https://opentofu.org/docs/v1.10/language/values/variables/#environment-variables) * [Complex-typed Values](https://opentofu.org/docs/v1.10/language/values/variables/#complex-typed-values) * [Values for Undeclared Variables](https://opentofu.org/docs/v1.10/language/values/variables/#values-for-undeclared-variables) * [Variable Definition Precedence](https://opentofu.org/docs/v1.10/language/values/variables/#variable-definition-precedence) --- # Write-only attributes | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/ephemerality/write-only-attributes/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Write-only attributes ===================== Note Write-only attributes can be used only with OpenTofu v1.11 onwards. This attribute is only found in [`managed resources`](https://opentofu.org/docs/v1.11/language/resources/) that are designed to accept transient values that will never be stored in the state or plan. For example, a secret can be read by using an ephemeral resource and then passed into the write-only attribute `password_wo` of a managed resource. The lifecycle of these attributes is quite different compared with other types of attributes: * A write-only attribute exists only in the configuration section of a resource * A write-only attribute will always be written into the state and plan with a null value * A write-only attribute will always be returned as null from the provider even if in the configuration it had an actual value * A write-only attribute can reference regular and ephemeral values (normal attributes cannot reference ephemeral values) Rendering[​](https://opentofu.org/docs/v1.11/language/ephemerality/write-only-attributes/#rendering "Direct link to Rendering") -------------------------------------------------------------------------------------------------------------------------------- When present in the plan/apply cli output, it will _always_ be displayed as `(write-only attribute)`. Updating a write-only attribute[​](https://opentofu.org/docs/v1.11/language/ephemerality/write-only-attributes/#updating-a-write-only-attribute "Direct link to Updating a write-only attribute") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- As OpenTofu has no way to know what value is currently in the remote resource (ie: null value in the state) and doesn't know what value has been (or planned to be) stored remotely (ie: provider returns null value for these attributes), it cannot generate a change for such attributes. As a recommendation for the provider authors, alongside the write-only attribute, there should be included also a non-write-only attribute meant to instruct the provider that the value given in the configuration of the write-only attribute should be used to update the resource. For example, [aws\_secretsmanager\_secret\_version](https://search.opentofu.org/provider/hashicorp/aws/v6.11.0/docs/resources/secretsmanager_secret_version) offers 2 fields for this: `secret_string_wo` which is the write-only attribute and `secret_string_wo_version` that is the non-write-only attribute. By changing the value of `secret_string_wo_version` from what is stored currently in the state, provider will trigger an update of the `secret_string_wo` attribute with the value provided in the configuration. Example[​](https://opentofu.org/docs/v1.11/language/ephemerality/write-only-attributes/#example "Direct link to Example") -------------------------------------------------------------------------------------------------------------------------- For an in-depth example on how to use write-only attributes, please refer to [this example](https://opentofu.org/docs/v1.11/language/ephemerality/#usage-example) . * [Rendering](https://opentofu.org/docs/v1.11/language/ephemerality/write-only-attributes/#rendering) * [Updating a write-only attribute](https://opentofu.org/docs/v1.11/language/ephemerality/write-only-attributes/#updating-a-write-only-attribute) * [Example](https://opentofu.org/docs/v1.11/language/ephemerality/write-only-attributes/#example) --- # Backend Type: s3 | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Backend Type: s3 ================ Stores the state as a given key in a given bucket on [Amazon S3](https://aws.amazon.com/s3/) . This backend supports multiple locking mechanisms. The preferred one is a native S3 locking via conditional writes with `If-None-Match` header. This can be enabled by setting `use_lockfile=true`. Another option is to use [Dynamo DB](https://aws.amazon.com/dynamodb/) locking, which can be enabled by setting the `dynamodb_table` field to an existing DynamoDB table name. A single DynamoDB table can be used to lock multiple remote state files. OpenTofu generates key names that include the values of the `bucket` and `key` variables. Warning It is highly recommended that you enable [Bucket Versioning](https://docs.aws.amazon.com/AmazonS3/latest/userguide/manage-versioning-examples.html) on the S3 bucket to allow for state recovery in the case of accidental deletions and human error. Note For a smooth transition to the S3 locking, please read the [dedicated section](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#s3-state-locking) . Example Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#example-configuration "Direct link to Example Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------ Code Block terraform { backend "s3" { bucket = "mybucket" key = "path/to/my/key" region = "us-east-1" }} This assumes we have a bucket created called `mybucket`. The OpenTofu state is written to the key `path/to/my/key`. Note that for the access credentials we recommend using a [partial configuration](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#partial-configuration) . ### S3 Bucket Permissions[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#s3-bucket-permissions "Direct link to S3 Bucket Permissions") OpenTofu will need the following AWS IAM permissions on the target backend bucket: * `s3:ListBucket` on `arn:aws:s3:::mybucket` * `s3:GetObject` on `arn:aws:s3:::mybucket/path/to/my/key` * `s3:PutObject` on `arn:aws:s3:::mybucket/path/to/my/key` * `s3:DeleteObject` on `arn:aws:s3:::mybucket/path/to/my/key` This is seen in the following AWS IAM Statement: Code Block { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::mybucket" }, { "Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"], "Resource": "arn:aws:s3:::mybucket/path/to/my/key" } ]} Note AWS can control access to S3 buckets with either IAM policies attached to users/groups/roles (like the example above) or resource policies attached to bucket objects (which look similar but also require a `Principal` to indicate which entity has those permissions). For more details, see Amazon's documentation about [S3 access control](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html) . ### DynamoDB Table Permissions[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#dynamodb-table-permissions "Direct link to DynamoDB Table Permissions") If you are using state locking, OpenTofu will need the following AWS IAM permissions on the DynamoDB table (`arn:aws:dynamodb:::table/mytable`): * `dynamodb:DescribeTable` * `dynamodb:GetItem` * `dynamodb:PutItem` * `dynamodb:DeleteItem` This is seen in the following AWS IAM Statement: Code Block { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "dynamodb:DescribeTable", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:DeleteItem" ], "Resource": "arn:aws:dynamodb:*:*:table/mytable" } ]} Data Source Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#data-source-configuration "Direct link to Data Source Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ To make use of the S3 remote state in another configuration, use the [`terraform_remote_state` data source](https://opentofu.org/docs/v1.10/language/state/remote-state-data/) . Code Block data "terraform_remote_state" "network" { backend = "s3" config = { bucket = "tofu-state-prod" key = "network/terraform.tfstate" region = "us-east-1" }} The `terraform_remote_state` data source will return all of the root module outputs defined in the referenced remote state (but not any outputs from nested modules unless they are explicitly output again in the root). An example output might look like: Code Block data.terraform_remote_state.network: id = 2016-10-29 01:57:59.780010914 +0000 UTC addresses.# = 2 addresses.0 = 52.207.220.222 addresses.1 = 54.196.78.166 backend = s3 config.% = 3 config.bucket = tofu-state-prod config.key = network/terraform.tfstate config.region = us-east-1 elb_address = web-elb-790251200.us-east-1.elb.amazonaws.com public_subnet_id = subnet-1e05dd33 Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#configuration "Direct link to Configuration") ------------------------------------------------------------------------------------------------------------------------------ This backend requires the configuration of the AWS Region and S3 state storage. Other configuration, such as enabling DynamoDB state locking, is optional. ### Credentials and Shared Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#credentials-and-shared-configuration "Direct link to Credentials and Shared Configuration") Warning We recommend using environment variables to supply credentials and other sensitive data. If you use `-backend-config` or hardcode these values directly in your configuration, OpenTofu will include these values in both the `.terraform` subdirectory and in plan files. Refer to [Credentials and Sensitive Data](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#credentials-and-sensitive-data) for details. The following configuration is required: * `region` - (Required) AWS Region of the S3 Bucket and DynamoDB Table (if used). This can also be sourced from the `AWS_DEFAULT_REGION` and `AWS_REGION` environment variables. The following configuration is optional: * `access_key` - (Optional) AWS access key. If configured, must also configure `secret_key`. This can also be sourced from the `AWS_ACCESS_KEY_ID` environment variable, AWS shared credentials file (e.g. `~/.aws/credentials`), or AWS shared configuration file (e.g. `~/.aws/config`). * `secret_key` - (Optional) AWS access key. If configured, must also configure `access_key`. This can also be sourced from the `AWS_SECRET_ACCESS_KEY` environment variable, AWS shared credentials file (e.g. `~/.aws/credentials`), or AWS shared configuration file (e.g. `~/.aws/config`). * `iam_endpoint` - (Optional) **Deprecated** Custom endpoint for the AWS Identity and Access Management (IAM) API. This can also be sourced from the `AWS_IAM_ENDPOINT` environment variable. * `max_retries` - (Optional) The maximum number of times an AWS API request is retried on retryable failure. Defaults to 5. * `retry_mode` - (Optional) Specifies how retries are attempted. Valid values are `standard` and `adaptive`. This can also be sourced from the `AWS_RETRY_MODE` environment variable. * `profile` - (Optional) Name of AWS profile in AWS shared credentials file (e.g. `~/.aws/credentials`) or AWS shared configuration file (e.g. `~/.aws/config`) to use for credentials and/or configuration. This can also be sourced from the `AWS_PROFILE` environment variable. * `shared_credentials_file` - (Optional) **Deprecated** Path to the AWS shared credentials file. Defaults to `~/.aws/credentials`. * `shared_credentials_files` - (Optional) List of paths to AWS shared credentials files. Defaults to `~/.aws/credentials`. This can also be sourced from the `AWS_SHARED_CREDENTIALS_FILE` environment variable. * `shared_config_files` - (Optional) List of paths to AWS shared configuration files. Defaults to `~/.aws/config`. This can also be sourced from the `AWS_SHARED_CONFIG_FILE` environment variable. * `skip_s3_checksum` - (Optional) Do not include checksum in the input when uploading S3 Objects. Useful for non AWS S3 APIs which do not support checksum validation. * `skip_credentials_validation` - (Optional) Skip credentials validation via the STS API. * `skip_region_validation` - (Optional) Skip validation of provided region name. * `skip_metadata_api_check` - (Optional) Skip usage of EC2 Metadata API. * `skip_requesting_account_id` - (Optional) Skip requesting the account ID. Useful for AWS API implementations that do not have the IAM, STS API, or metadata API. * `sts_endpoint` - (Optional) **Deprecated** Custom endpoint for the AWS Security Token Service (STS) API. This can also be sourced from the `AWS_STS_ENDPOINT` environment variable. * `sts_region` - (Optional) AWS region for STS. If unset, AWS will use the same region for STS as other non-STS operations. * `token` - (Optional) Multi-Factor Authentication (MFA) token. This can also be sourced from the `AWS_SESSION_TOKEN` environment variable. * `allowed_account_ids` (Optional): A list of permitted AWS account IDs to safeguard against accidental disruption of a live environment. This option conflicts with `forbidden_account_ids`. * `forbidden_account_ids` (Optional): A list of prohibited AWS account IDs to prevent unintentional disruption of a live environment. This option conflicts with `allowed_account_ids`. * `custom_ca_bundle` - File containing custom root and intermediate certificates. Can also be configured using the `AWS_CA_BUNDLE` environment variable. * `ec2_metadata_service_endpoint` - Address of the EC2 metadata service (IMDS) endpoint to use. This can also be sourced from the `AWS_EC2_METADATA_SERVICE_ENDPOINT` environment variable. * `ec2_metadata_service_endpoint_mode` - Mode to use in communicating with the metadata service. Valid values are `IPv4` and `IPv6`. This can also be sourced from the `AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE` environment variable. * `http_proxy` - (Optional) The address of an HTTP proxy to use when accessing the AWS API. This can also be sourced from the `HTTP_PROXY` environment variable. * `https_proxy` - (Optional) The address of an HTTPS proxy to use when accessing the AWS API. This can also be sourced from the `HTTPS_PROXY` environment variable. * `no_proxy` - (Optional) Comma-separated values which specify hosts that should be excluded from proxying when accessing the AWS API. This can also be sourced from the `NO_PROXY` environment variable. Find more details [here](https://cs.opensource.google/go/x/net/+/refs/tags/v0.17.0:http/httpproxy/proxy.go;l=38-50) . * `insecure` - (Optional) Explicitly allow the backend to perform "insecure" SSL requests; default is `false`. * `use_dualstack_endpoint` - (Optional) Resolve an endpoint with DualStack capability. * `use_fips_endpoint` - (Optional) Resolve an endpoint with FIPS capability. #### Customizing AWS API Endpoints[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#customizing-aws-api-endpoints "Direct link to Customizing AWS API Endpoints") The optional `endpoints` argument contains the following options: * `s3` - (Optional) Use this to set a custom endpoint URL for the AWS S3 API. This can also be sourced from the `AWS_ENDPOINT_URL_S3` environment variable or the deprecated environment variable `AWS_S3_ENDPOINT`. * `iam` - (Optional) Use this to set a custom endpoint URL for the AWS IAM API. This can also be sourced from the `AWS_ENDPOINT_URL_IAM` environment variable or the deprecated environment variable `AWS_IAM_ENDPOINT`. * `sts` - (Optional) Use this to set a custom endpoint URL for the AWS STS API. This can also be sourced from the `AWS_ENDPOINT_URL_STS` environment variable or the deprecated environment variable `AWS_STS_ENDPOINT`. * `dynamodb` - (Optional) Use this to set a custom endpoint URL for the AWS DynamoDB API. This can also be sourced from the `AWS_ENDPOINT_URL_DYNAMODB` environment variable or the deprecated environment variable `AWS_DYNAMODB_ENDPOINT`. Code Block terraform { backend "s3" { endpoints = { dynamodb = "http://localhost:4569" s3 = "http://localhost:4572" } }} #### Assume Role Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#assume-role-configuration "Direct link to Assume Role Configuration") Assuming an IAM Role is optional and can be configured in two ways. The preferred way is to use the argument `assume_role`, as the other, the other method is deprecated. The argument `assume_role` contains the following arguments: * `role_arn` - (Required) The Amazon Resource Name (ARN) of the IAM Role to be assumed. * `duration` - (Optional) Specifies the validity period for individual credentials. These credentials are automatically renewed, with the maximum renewal defined by the AWS account. The duration should be specified in the format `hms`, with each unit being optional. For example, an hour and a half can be represented as `1h30m` or simply `90m`. The duration must be within the range of 15 minutes (15m) to 12 hours (12h). * `external_id` - (Optional) An external identifier to use when assuming the role. * `policy` - (Optional) JSON representation of an IAM Policy that further restricts permissions for the IAM Role being assumed. * `policy_arns` - (Optional) A set of Amazon Resource Names (ARNs) for IAM Policies that further limit permissions for the assumed IAM Role. * `session_name` - (Optional) The session name to be used when assuming the role. * `tags` - (Optional) A map of tags to be associated with the assumed role session. * `transitive_tag_keys` - (Optional) A set of tag keys from the assumed role session to be passed to any subsequent sessions. The following arguments on the top level are deprecated: * `assume_role_duration_seconds` - (Optional) Number of seconds to restrict the assume role session duration. Use `assume_role.duration` instead. * `assume_role_policy` - (Optional) IAM Policy JSON describing further restricting permissions for the IAM Role being assumed. Use `assume_role.policy` instead. * `assume_role_policy_arns` - (Optional) Set of Amazon Resource Names (ARNs) of IAM Policies describing further restricting permissions for the IAM Role being assumed. Use `assume_role.policy_arns` instead. * `assume_role_tags` - (Optional) Map of assume role session tags. Use `assume_role.tags` instead. * `assume_role_transitive_tag_keys` - (Optional) Set of assume role session tag keys to pass to any subsequent sessions. Use `assume_role.transitive_tag_keys` instead. * `external_id` - (Optional) External identifier to use when assuming the role. Use `assume_role.external_id` instead. * `role_arn` - (Optional) Amazon Resource Name (ARN) of the IAM Role to assume. Use `assume_role.role_arn` instead. * `session_name` - (Optional) Session name to use when assuming the role. Use `assume_role.session_name` instead. Code Block terraform { backend "s3" { bucket = "mybucket" key = "my/key.tfstate" region = "us-east-1" assume_role = { role_arn = "arn:aws:iam::ACCOUNT-ID:role/Opentofu" } }} #### Assume Role With Web Identity Configuration[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#assume-role-with-web-identity-configuration "Direct link to Assume Role With Web Identity Configuration") The following `assume_role_with_web_identity` configuration block is optional: * `role_arn` - (Required) Amazon Resource Name (ARN) of the IAM Role to assume. Can also be set with the `AWS_ROLE_ARN` environment variable. * `duration` - (Optional) The duration individual credentials will be valid. Credentials are automatically renewed up to the maximum defined by the AWS account. Specified using the format `hms` with any unit being optional. For example, an hour and a half can be specified as `1h30m` or `90m`. Must be between 15 minutes (15m) and 12 hours (12h). * `policy` - (Optional) IAM Policy JSON describing further restricting permissions for the IAM Role being assumed. * `policy_arns` - (Optional) Set of Amazon Resource Names (ARNs) of IAM Policies describing further restricting permissions for the IAM Role being assumed. * `session_name` - (Optional) Session name to use when assuming the role. Can also be set with the `AWS_ROLE_SESSION_NAME` environment variable. * `web_identity_token` - (Optional) The value of a web identity token from an OpenID Connect (OIDC) or OAuth provider. One of `web_identity_token` or `web_identity_token_file` is required. * `web_identity_token_file` - (Optional) File containing a web identity token from an OpenID Connect (OIDC) or OAuth provider. One of `web_identity_token_file` or `web_identity_token` is required. Can also be set with the `AWS_WEB_IDENTITY_TOKEN_FILE` environment variable. Code Block terraform { backend "s3" { bucket = "mybucket" key = "my/key.tfstate" region = "us-east-1" assume_role_with_web_identity = { role_arn = "arn:aws:iam::ACCOUNT-ID:role/Opentofu" web_identity_token = "" } }} It's possible to constrain the assumed role by providing a policy. Code Block terraform { backend "s3" { bucket = "mybucket" key = "my/key.tfstate" region = "us-east-1" assume_role_with_web_identity = { role_arn = "arn:aws:iam::ACCOUNT-ID:role/Opentofu" web_identity_token = "" policy = <<-JSON { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:*", "Resource": [ "arn:aws:s3:::mybucket/*", "arn:aws:s3:::mybucket" ] } ] } JSON } }} ### S3 State Storage[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#s3-state-storage "Direct link to S3 State Storage") The following configuration is required: * `bucket` - (Required) Name of the S3 Bucket. * `key` - (Required) Path to the state file inside the S3 Bucket. When using a non-default [workspace](https://opentofu.org/docs/v1.10/language/state/workspaces/) , the state path will be `/workspace_key_prefix/workspace_name/key` (see also the `workspace_key_prefix` configuration). The following configuration is optional: * `acl` - (Optional) [Canned ACL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl) to be applied to the state file. * `encrypt` - (Optional) Enable [server side encryption](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingServerSideEncryption.html) of the state file. * `endpoint` - (Optional) **Deprecated** Custom endpoint for the AWS S3 API. This can also be sourced from the `AWS_S3_ENDPOINT` environment variable. * `force_path_style` - (Optional) **Deprecated** Enable path-style S3 URLs (`https:///` instead of `https://.`). Use `use_path_style` instead. * `use_path_style` - (Optional) Enable path-style S3 URLs (`https:///` instead of `https://.`). * `kms_key_id` - (Optional) Amazon Resource Name (ARN) of a Key Management Service (KMS) Key to use for encrypting the state. Note that if this value is specified, OpenTofu will need `kms:Encrypt`, `kms:Decrypt` and `kms:GenerateDataKey` permissions on this KMS key. * `sse_customer_key` - (Optional) The key to use for encrypting state with [Server-Side Encryption with Customer-Provided Keys (SSE-C)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ServerSideEncryptionCustomerKeys.html) . This is the base64-encoded value of the key, which must decode to 256 bits. This can also be sourced from the `AWS_SSE_CUSTOMER_KEY` environment variable, which is recommended due to the sensitivity of the value. Setting it inside an OpenTofu file will cause it to be persisted to disk in `terraform.tfstate`. * `workspace_key_prefix` - (Optional) Prefix applied to the state path inside the bucket. This is only relevant when using a non-default workspace. Defaults to `env:`. ### DynamoDB State Locking[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#dynamodb-state-locking "Direct link to DynamoDB State Locking") The following configuration is optional: * `dynamodb_endpoint` - (Optional) **Deprecated** Custom endpoint for the AWS DynamoDB API. This can also be sourced from the `AWS_DYNAMODB_ENDPOINT` environment variable. * `dynamodb_table` - (Optional) Name of DynamoDB Table to use for state locking and consistency. The table must have a partition key named `LockID` with type of `String`. If not configured, state locking will be disabled. ### S3 State Locking[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#s3-state-locking "Direct link to S3 State Locking") * `use_lockfile` - (Optional) Enable locking directly into the configured bucket for the state. To migrate from DynamoDB to S3 locking, the following steps can be followed: 1. The new attribute `use_lockfile=true` can be added alongside `dynamodb_table`: * With both attributes specified, OpenTofu will try to acquire the lock first in S3 and if successful, will try to acquire the lock in DynamoDB. In this case, the lock will be considered acquired only when both (S3 and DynamoDB) locks were acquired successfully. * Later, after a baking period with both locking mechanisms enabled, if no issues encountered, remove the `dynamodb_table` attribute. Now, you are solely on the S3 locking. * **Info:** Keeping both locking mechanisms enabled, ensures that nobody will acquire the lock regardless of having or not the latest configuration. 2. The new attribute `use_lockfile=true` can be added and `dynamodb_table` removed: * This will switch from DynamoDB to S3 locking. **Caution:** when the updated configuration is executed from multiple places (multiple machines, pipelines on PRs, etc), you might get into issues where one outdated copy of the configuration is using DynamoDB locking and the one updated is using S3 locking. This could end up in concurrent access on the same state file. * Once the state is updated by using this approach, the state digest that OpenTofu was storing in DynamoDB (for data consistency checks) will get stale. If you wish to go back to DynamoDB locking, **the old digest needs to be cleaned up manually**. Note Remember, any changes to the `backend` block will require to run `tofu init -reconfigure`. Note As mentioned in the beginning of this page, OpenTofu recommends to have versioning enabled on the S3 bucket where state file(s) are stored. By setting `use_lockfile=true`, acquiring and releasing locks will add a good amount of writes and reads to the bucket. Therefore, for a versioning-enabled bucket, the number of versions for that object could grow significantly. Even though the cost should be negligible for the locking objects, a lifecycle configuration of the S3 bucket to limit the number of versions of an object would be advised. When it comes to the workspace usage, the S3 locking will behave normally, storing the lock file right next to its related state object. Multi-account AWS Architecture[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#multi-account-aws-architecture "Direct link to Multi-account AWS Architecture") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A common architectural pattern is for an organization to use a number of separate AWS accounts to isolate different teams and environments. For example, a "staging" system will often be deployed into a separate AWS account than its corresponding "production" system, to minimize the risk of the staging environment affecting production infrastructure, whether via rate limiting, misconfigured access controls, or other unintended interactions. The S3 backend can be used in a number of different ways that make different tradeoffs between convenience, security, and isolation in such an organization. This section describes one such approach that aims to find a good compromise between these tradeoffs, allowing use of [OpenTofu's workspaces feature](https://opentofu.org/docs/v1.10/language/state/workspaces/) to switch conveniently between multiple isolated deployments of the same configuration. Use this section as a starting-point for your approach, but note that you will probably need to make adjustments for the unique standards and regulations that apply to your organization. You will also need to make some adjustments to this approach to account for _existing_ practices within your organization, if for example other tools have previously been used to manage infrastructure. OpenTofu is an administrative tool that manages your infrastructure, and so ideally the infrastructure that is used by OpenTofu should exist outside of the infrastructure that OpenTofu manages. This can be achieved by creating a separate _administrative_ AWS account which contains the user accounts used by human operators and any infrastructure and tools used to manage the other accounts. Isolating shared administrative tools from your main environments has a number of advantages, such as avoiding accidentally damaging the administrative infrastructure while changing the target infrastructure, and reducing the risk that an attacker might abuse production infrastructure to gain access to the (usually more privileged) administrative infrastructure. ### Administrative Account Setup[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#administrative-account-setup "Direct link to Administrative Account Setup") Your administrative AWS account will contain at least the following items: * One or more [IAM user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html) for system administrators that will log in to maintain infrastructure in the other accounts. * Optionally, one or more [IAM groups](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html) to differentiate between different groups of users that have different levels of access to the other AWS accounts. * An [S3 bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html) that will contain the OpenTofu state files for each workspace. * A [DynamoDB table](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.TablesItemsAttributes) that will be used for locking to prevent concurrent operations on a single workspace. Provide the S3 bucket name and DynamoDB table name to OpenTofu within the S3 backend configuration using the `bucket` and `dynamodb_table` arguments respectively, and configure a suitable `workspace_key_prefix` to contain the states of the various workspaces that will subsequently be created for this configuration. ### Environment Account Setup[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#environment-account-setup "Direct link to Environment Account Setup") For the sake of this section, the term "environment account" refers to one of the accounts whose contents are managed by OpenTofu, separate from the administrative account described above. Your environment accounts will eventually contain your own product-specific infrastructure. Along with this it must contain one or more [IAM roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) that grant sufficient access for OpenTofu to perform the desired management tasks. ### Delegating Access[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#delegating-access "Direct link to Delegating Access") Each Administrator will run OpenTofu using credentials for their IAM user in the administrative account. [IAM Role Delegation](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html) is used to grant these users access to the roles created in each environment account. Full details on role delegation are covered in the AWS documentation linked above. The most important details are: * Each role's _Assume Role Policy_ must grant access to the administrative AWS account, which creates a trust relationship with the administrative AWS account so that its users may assume the role. * The users or groups within the administrative account must also have a policy that creates the converse relationship, allowing these users or groups to assume that role. Since the purpose of the administrative account is only to host tools for managing other accounts, it is useful to give the administrative accounts restricted access only to the specific operations needed to assume the environment account role and access the OpenTofu state. By blocking all other access, you remove the risk that user error will lead to staging or production resources being created in the administrative account by mistake. When configuring OpenTofu, use either environment variables or the standard credentials file `~/.aws/credentials` to provide the administrator user's IAM credentials within the administrative account to both the S3 backend _and_ to OpenTofu's AWS provider. Use conditional configuration to pass a different `assume_role` value to the AWS provider depending on the selected workspace. For example: Code Block variable "workspace_iam_roles" { default = { staging = "arn:aws:iam::STAGING-ACCOUNT-ID:role/OpenTofu" production = "arn:aws:iam::PRODUCTION-ACCOUNT-ID:role/OpenTofu" }}provider "aws" { # No credentials explicitly set here because they come from either the # environment or the global credentials file. assume_role { role_arn = "${var.workspace_iam_roles[terraform.workspace]}" }} If workspace IAM roles are centrally managed and shared across many separate OpenTofu configurations, the role ARNs could also be obtained via a data source such as [`terraform_remote_state`](https://opentofu.org/docs/v1.10/language/state/remote-state-data/) to avoid repeating these values. ### Creating and Selecting Workspaces[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#creating-and-selecting-workspaces "Direct link to Creating and Selecting Workspaces") With the necessary objects created and the backend configured, run `tofu init` to initialize the backend and establish an initial workspace called "default". This workspace will not be used, but is created automatically by OpenTofu as a convenience for users who are not using the workspaces feature. Create a workspace corresponding to each key given in the `workspace_iam_roles` variable value above: Code Block $ tofu workspace new stagingCreated and switched to workspace "staging"!...$ tofu workspace new productionCreated and switched to workspace "production"!... Due to the `assume_role` setting in the AWS provider configuration, any management operations for AWS resources will be performed via the configured role in the appropriate environment AWS account. The backend operations, such as reading and writing the state from S3, will be performed directly as the administrator's own user within the administrative account. Code Block $ tofu workspace select staging$ tofu apply... ### Running OpenTofu in Amazon EC2[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#running-opentofu-in-amazon-ec2 "Direct link to Running OpenTofu in Amazon EC2") Teams that make extensive use of OpenTofu for infrastructure management often run OpenTofu in automation to ensure a consistent operating environment and to limit access to the various secrets and other sensitive information that OpenTofu configurations tend to require. When running OpenTofu in an automation tool running on an Amazon EC2 instance, consider running this instance in the administrative account and using an [instance profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html) in place of the various administrator IAM users suggested above. An IAM instance profile can also be granted cross-account delegation access via an IAM policy, giving this instance the access it needs to run OpenTofu. To isolate access to different environment accounts, use a separate EC2 instance for each target account so that its access can be limited only to the single account. Similar approaches can be taken with equivalent features in other AWS compute services, such as ECS. ### Protecting Access to Workspace State[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#protecting-access-to-workspace-state "Direct link to Protecting Access to Workspace State") In a simple implementation of the pattern described in the prior sections, all users have access to read and write states for all workspaces. In many cases it is desirable to apply more precise access constraints to the OpenTofu state objects in S3, so that for example only trusted administrators are allowed to modify the production state, or to control _reading_ of a state that contains sensitive information. Amazon S3 supports fine-grained access control on a per-object-path basis using IAM policy. A full description of S3's access control mechanism is beyond the scope of this guide, but an example IAM policy granting access to only a single state object within an S3 bucket is shown below: Code Block { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::myorg-tofu-states" }, { "Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject"], "Resource": "arn:aws:s3:::myorg-tofu-states/myapp/production/tfstate" } ]} It is also possible to apply fine-grained access control to the DynamoDB table used for locking. When OpenTofu puts the state lock in place during `tofu plan`, it stores the full state file as a document and sets the s3 object key as the partition key for the document. After the state lock is released, OpenTofu places a digest of the updated state file in DynamoDB. The key is similar to the one for the original state file, but is suffixed with `-md5`. The example below shows a simple IAM policy that allows the backend operations role to perform these operations: Code Block { "Version": "2012-10-17", "Statement": [ { "Effect" : "Allow", "Action" : [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:UpdateItem" ], "Resource" : ["arn:aws:dynamodb:*:*:table/myorg-state-lock-table"], "Condition" : { "ForAllValues:StringEquals" : { "dynamodb:LeadingKeys" : [ "myorg-tofu-states/myapp/production/tfstate", // during a state lock the full state file is stored with this key "myorg-tofu-states/myapp/production/tfstate-md5" // after the lock is released a hash of the statefile's contents are stored with this key ] } } } ]} Refer to the [AWS documentation on DynamoDB fine-grained locking](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/specifying-conditions.html) for more details. ### Configuring Custom User-Agent Information[​](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#configuring-custom-user-agent-information "Direct link to Configuring Custom User-Agent Information") Note this feature is optional. By default, the underlying AWS client used by the OpenTofu AWS Provider creates requests with User-Agent headers including information about OpenTofu and AWS Go SDK versions. To provide additional information in the User-Agent headers, the `TF_APPEND_USER_AGENT` environment variable can be set and its value will be directly added to HTTP requests. e.g. Code Block $ export TF_APPEND_USER_AGENT="JenkinsAgent/i-12345678 BuildID/1234 (Optional Extra Information)" * [Example Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#example-configuration) * [S3 Bucket Permissions](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#s3-bucket-permissions) * [DynamoDB Table Permissions](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#dynamodb-table-permissions) * [Data Source Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#data-source-configuration) * [Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#configuration) * [Credentials and Shared Configuration](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#credentials-and-shared-configuration) * [S3 State Storage](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#s3-state-storage) * [DynamoDB State Locking](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#dynamodb-state-locking) * [S3 State Locking](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#s3-state-locking) * [Multi-account AWS Architecture](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#multi-account-aws-architecture) * [Administrative Account Setup](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#administrative-account-setup) * [Environment Account Setup](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#environment-account-setup) * [Delegating Access](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#delegating-access) * [Creating and Selecting Workspaces](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#creating-and-selecting-workspaces) * [Running OpenTofu in Amazon EC2](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#running-opentofu-in-amazon-ec2) * [Protecting Access to Workspace State](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#protecting-access-to-workspace-state) * [Configuring Custom User-Agent Information](https://opentofu.org/docs/v1.10/language/settings/backends/s3/#configuring-custom-user-agent-information) --- # Installing OpenTofu from GitHub Releases | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/intro/install/standalone/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Installing OpenTofu from GitHub Releases ======================================== Using the installer script[​](https://opentofu.org/docs/v1.11/intro/install/standalone/#using-the-installer-script "Direct link to Using the installer script") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- * Linux/MacOS/BSD/Unix (POSIX) * Windows (PowerShell) Code Block # Download the installer script:curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh -o install-opentofu.sh# Alternatively: wget --secure-protocol=TLSv1_2 --https-only https://get.opentofu.org/install-opentofu.sh -O install-opentofu.sh# Grant execution permissions:chmod +x install-opentofu.sh# Please inspect the downloaded script at this point.# Run the installer:./install-opentofu.sh --install-method standalone# Remove the installer:rm -f install-opentofu.sh Note The standalone installer verifies the integrity of the downloaded files. You need to install [cosign](https://docs.sigstore.dev/system_config/installation/) , [GnuPG](https://gnupg.org/) , or disable the integrity verification by using the `--skip-verify` option. Code Block # Download the installer script:Invoke-WebRequest -outfile "install-opentofu.ps1" -uri "https://get.opentofu.org/install-opentofu.ps1"# Please inspect the downloaded script at this point.# Run the installer:& .\install-opentofu.ps1 -installMethod standalone# Remove the installer:Remove-Item install-opentofu.ps1 Note If you run into script execution policy issues when running this script, please run `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process` before running the installer. Note The standalone installer verifies the integrity of the downloaded files. You need to install [cosign](https://docs.sigstore.dev/system_config/installation/) , [GnuPG](https://gnupg.org/) , or disable the integrity verification by using the `-skipVerify` option. Using OpenTofu as a standalone binary[​](https://opentofu.org/docs/v1.11/intro/install/standalone/#using-opentofu-as-a-standalone-binary "Direct link to Using OpenTofu as a standalone binary") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can run OpenTofu without installation as a standalone binary. You can [download the latest release](https://github.com/opentofu/opentofu/releases/latest/) for your operating system from the [GitHub releases page](https://github.com/opentofu/opentofu/releases/latest/) , unpack the zip and start using it. For easier updates, we recommend using the **non-portable packaged versions for your operating system**. Verify the file integrity[​](https://opentofu.org/docs/v1.11/intro/install/standalone/#verify-the-file-integrity "Direct link to Verify the file integrity") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Please download the `tofu_YOURVERSION_SHA256SUMS` file from the release. This file contains the SHA256 checksums for all files. You can verify the integrity of your file by running: * Linux (sha256sum) * MacOS (shasum) * Windows (PowerShell) Code Block ZIPFILE=tofu_*.zipCHECKSUM=$(sha256sum "${ZIPFILE}" | cut -f 1 -d ' ')EXPECTED_CHECKSUM=$(grep "${ZIPFILE}" tofu_*_SHA256SUMS | cut -f 1 -d ' ')if [ "${CHECKSUM}" = "${EXPECTED_CHECKSUM}" ]; then echo "OK"else echo "MISMATCH"fi Code Block ZIPFILE=tofu_*.zipCHECKSUM=$(shasum -a 256 "tofu_*.zip" | cut -f 1 -d ' ')EXPECTED_CHECKSUM=$(grep "${ZIPFILE}" tofu_*_SHA256SUMS | cut -f 1 -d ' ')if [ "${CHECKSUM}" = "${EXPECTED_CHECKSUM}" ]; then echo "OK"else echo "MISMATCH"fi Code Block $zipFile="tofu_YOURVERSION_REPLACEME.zip"$checksum = $(Get-FileHash -Algorithm SHA256 $zipFile).Hash$expectedChecksum = $((Get-Content "tofu_YOURVERSION_REPLACEME_SHA256SUMS" | Select-String -Pattern $zipFile) -split '\s+')[0]if ($realHash -ne $expectedHash) { Write-Error "Checksum mismatch"} Verifying the binaries with Cosign ================================== After you have verified the checksums, you can verify the integrity of the checksum file itself with [Cosign](https://docs.sigstore.dev/system_config/installation/) . Please make sure you have installed Cosign and download the `tofu_YOURVERSION_SHA256SUMS.pem` and `tofu_YOURVERSION_SHA256SUMS.sig` files for your release. You can then run the integrity verification: * Linux/MacOS/BSD/UNIX (POSIX) * Windows (PowerShell) Code Block OPENTOFU_VERSION_MAJORMINOR="Add your OpenTofu major and minor version here"IDENTITY="https://github.com/opentofu/opentofu/.github/workflows/release.yml@refs/heads/v${OPENTOFU_VERSION_MAJORMINOR}"# For alpha and beta builds use /maincosign \ verify-blob \ --certificate-identity "${IDENTITY}" \ --signature tofu_*.sig \ --certificate tofu_*.pem \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \ tofu_*_SHA256SUMS Code Block $version = [version]"YOUR_OPENTOFU_VERSION"$identity = "https://github.com/opentofu/opentofu/.github/workflows/release.yml@refs/heads/v${version.Major}.${version.Minor}"# For alpha and beta builds use /maincosign.exe ` verify-blob ` --certificate-identity $identity ` --signature "tofu_YOURVERSION_REPLACEME.sig" ` --certificate "tofu_YOURVERSION_REPLACEME.pem" ` --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ` "tofu_YOURVERSION_REPLACEME_SHA256SUMS" * [Using the installer script](https://opentofu.org/docs/v1.11/intro/install/standalone/#using-the-installer-script) * [Using OpenTofu as a standalone binary](https://opentofu.org/docs/v1.11/intro/install/standalone/#using-opentofu-as-a-standalone-binary) * [Verify the file integrity](https://opentofu.org/docs/v1.11/intro/install/standalone/#verify-the-file-integrity) --- # OpenTofu Language Documentation | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page OpenTofu Language Documentation =============================== This is the documentation for OpenTofu's configuration language. It is relevant to users of [OpenTofu CLI](https://opentofu.org/docs/v1.11/cli/) , and [TACOS](https://opentofu.org/docs/v1.11/intro/tacos/) (TF Automation and Collaboration Software). OpenTofu's language is its primary user interface. Configuration files you write in OpenTofu language tell OpenTofu what plugins to install, what infrastructure to create, and what data to fetch. OpenTofu language also lets you define dependencies between resources and create multiple similar resources from a single configuration block. About the OpenTofu Language[​](https://opentofu.org/docs/v1.11/language/#about-the-opentofu-language "Direct link to About the OpenTofu Language") --------------------------------------------------------------------------------------------------------------------------------------------------- The main purpose of the OpenTofu language is declaring [resources](https://opentofu.org/docs/v1.11/language/resources/) , which represent infrastructure objects. All other language features exist only to make the definition of resources more flexible and convenient. An _OpenTofu configuration_ is a complete document in the OpenTofu language that tells OpenTofu how to manage a given collection of infrastructure. A configuration can consist of multiple files and directories. The syntax of the OpenTofu language consists of only a few basic elements: Code Block resource "aws_vpc" "main" { cidr_block = var.base_cidr_block} "" "" { # Block body = # Argument} * _Blocks_ are containers for other content and usually represent the configuration of some kind of object, like a resource. Blocks have a _block type,_ can have zero or more _labels,_ and have a _body_ that contains any number of arguments and nested blocks. Most of OpenTofu's features are controlled by top-level blocks in a configuration file. * _Arguments_ assign a value to a name. They appear within blocks. * _Expressions_ represent a value, either literally or by referencing and combining other values. They appear as values for arguments, or within other expressions. The OpenTofu language is declarative, describing an intended goal rather than the steps to reach that goal. The ordering of blocks and the files they are organized into are generally not significant; OpenTofu only considers implicit and explicit relationships between resources when determining an order of operations. ### Example[​](https://opentofu.org/docs/v1.11/language/#example "Direct link to Example") The following example describes a simple network topology for Amazon Web Services, just to give a sense of the overall structure and syntax of the OpenTofu language. Similar configurations can be created for other virtual network services, using resource types defined by other providers, and a practical network configuration will often contain additional elements not shown here. Code Block terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 1.0.4" } }}variable "aws_region" {}variable "base_cidr_block" { description = "A /16 CIDR range definition, such as 10.1.0.0/16, that the VPC will use" default = "10.1.0.0/16"}variable "availability_zones" { description = "A list of availability zones in which to create subnets" type = list(string)}provider "aws" { region = var.aws_region}resource "aws_vpc" "main" { # Referencing the base_cidr_block variable allows the network address # to be changed without modifying the configuration. cidr_block = var.base_cidr_block}resource "aws_subnet" "az" { # Create one subnet for each given availability zone. count = length(var.availability_zones) # For each subnet, use one of the specified availability zones. availability_zone = var.availability_zones[count.index] # By referencing the aws_vpc.main object, OpenTofu knows that the subnet # must be created only after the VPC is created. vpc_id = aws_vpc.main.id # Built-in functions and operators can be used for simple transformations of # values, such as computing a subnet address. Here we create a /20 prefix for # each subnet, using consecutive addresses for each availability zone, # such as 10.1.16.0/20 . cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 4, count.index+1)} * [About the OpenTofu Language](https://opentofu.org/docs/v1.11/language/#about-the-opentofu-language) * [Example](https://opentofu.org/docs/v1.11/language/#example) --- # Machine-Readable UI | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Machine-Readable UI =================== By default, many OpenTofu commands display UI output as unstructured text, intended to be read by a user via a terminal emulator. This text stream is not a stable interface for integrations. Some commands support a `-json` flag, which enables a structured JSON output mode with a defined interface. For long-running commands such as `plan`, `apply`, and `refresh` the `-json` flag outputs a stream of JSON UI messages, one per line. These can be processed one message at a time, with integrating software filtering, combining, or modifying the output as desired. The first message output has type `version`, and includes a `ui` key, which has value `"1.0"`. The semantics of this version are: * We will increment the minor version, e.g. `"1.1"`, for backward-compatible changes or additions. Ignore any object properties with unrecognized names to remain forward-compatible with future minor versions. * We will increment the major version, e.g. `"2.0"`, for changes that are not backward-compatible. Reject any input which reports an unsupported major version. We will introduce new major versions only within the bounds of [the OpenTofu 1.0 Compatibility Promises](https://opentofu.org/docs/v1.11/language/v1-compatibility-promises/) . Sample JSON Output[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#sample-json-output "Direct link to Sample JSON Output") --------------------------------------------------------------------------------------------------------------------------------------------- Below is sample output from running `tofu apply -json`: Code Block {"@level":"info","@message":"OpenTofu 1.6.0","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.275359-04:00","tofu":"0.15.4","type":"version","ui":"0.1.0"}{"@level":"info","@message":"random_pet.animal: Plan to create","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.705503-04:00","change":{"resource":{"addr":"random_pet.animal","module":"","resource":"random_pet.animal","implied_provider":"random","resource_type":"random_pet","resource_name":"animal","resource_key":null},"action":"create"},"type":"planned_change"}{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.705638-04:00","changes":{"add":1,"change":0,"remove":0,"operation":"plan"},"type":"change_summary"}{"@level":"info","@message":"random_pet.animal: Creating...","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.825308-04:00","hook":{"resource":{"addr":"random_pet.animal","module":"","resource":"random_pet.animal","implied_provider":"random","resource_type":"random_pet","resource_name":"animal","resource_key":null},"action":"create"},"type":"apply_start"}{"@level":"info","@message":"random_pet.animal: Creation complete after 0s [id=smart-lizard]","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.826179-04:00","hook":{"resource":{"addr":"random_pet.animal","module":"","resource":"random_pet.animal","implied_provider":"random","resource_type":"random_pet","resource_name":"animal","resource_key":null},"action":"create","id_key":"id","id_value":"smart-lizard","elapsed_seconds":0},"type":"apply_complete"}{"@level":"info","@message":"Apply complete! Resources: 1 added, 0 changed, 0 destroyed.","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.869168-04:00","changes":{"add":1,"change":0,"remove":0,"operation":"apply"},"type":"change_summary"}{"@level":"info","@message":"Outputs: 1","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.869280-04:00","outputs":{"pets":{"sensitive":false,"type":"string","value":"smart-lizard"}},"type":"outputs"} Each line consists of a JSON object with several keys common to all messages. These are: * `@level`: this is normally "info", but can be "error" or "warn" when showing diagnostics * `@message`: a human-readable summary of the contents of this message * `@module`: always "tofu.ui" when rendering UI output * `@timestamp`: an RFC3339 timestamp of when the message was output * `type`: defines which kind of message this is and determines how to interpret other keys which may be present Clients presenting the logs as a user interface should handle unexpected message types by presenting at least the `@message` field to the user. Messages will be emitted as events occur to trigger them. This means that messages related to several resources may be interleaved (if OpenTofu is running with concurrency above 1). The [`resource` object value](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) can be used to link multiple messages about a single resource. Message Types[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#message-types "Direct link to Message Types") ------------------------------------------------------------------------------------------------------------------------------ The following message types are supported: ### Generic Messages[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#generic-messages "Direct link to Generic Messages") * `version`: information about the OpenTofu version and the version of the schema used for the following messages * `log`: unstructured human-readable log lines * `diagnostic`: diagnostic warning or error messages; [see the `tofu validate` docs for more details on the format](https://opentofu.org/docs/v1.11/cli/commands/validate/#json) ### Operation Results[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#operation-results "Direct link to Operation Results") * `resource_drift`: describes a detected change to a single resource made outside of OpenTofu * `planned_change`: describes a planned change to a single resource * `change_summary`: summary of all planned or applied changes * `outputs`: list of all root module outputs ### Resource Progress[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-progress "Direct link to Resource Progress") * `apply_start`, `apply_progress`, `apply_complete`, `apply_errored`: sequence of messages indicating progress of a single resource through apply * `provision_start`, `provision_progress`, `provision_complete`, `provision_errored`: sequence of messages indicating progress of a single provisioner step * `refresh_start`, `refresh_complete`: sequence of messages indicating progress of a single resource through refresh Version Message[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#version-message "Direct link to Version Message") ------------------------------------------------------------------------------------------------------------------------------------ A machine-readable UI command output will always begin with a `version` message. The following message-specific keys are defined: * `tofu`: the OpenTofu version which emitted this message * `ui`: the machine-readable UI schema version defining the meaning of the following messages ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example "Direct link to Example") Code Block { "@level": "info", "@message": "OpenTofu 0.15.4", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.275359-04:00", "tofu": "0.15.4", "type": "version", "ui": "0.1.0"} Resource Drift[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-drift "Direct link to Resource Drift") --------------------------------------------------------------------------------------------------------------------------------- If drift is detected during planning, OpenTofu will emit a `resource_drift` message for each resource which has changed outside of OpenTofu. This message has an embedded `change` object with the following keys: * `resource`: object describing the address of the resource to be changed; see [resource object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) below for details * `action`: the action planned to be taken for the resource. Values: `update`, `delete`. This message does not include details about the exact changes which caused the change to be planned. That information is available in [the JSON plan output](https://opentofu.org/docs/v1.11/internals/json-format/) . ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-1 "Direct link to Example") Code Block { "@level": "info", "@message": "random_pet.animal: Drift detected (update)", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.705503-04:00", "change": { "resource": { "addr": "random_pet.animal", "module": "", "resource": "random_pet.animal", "implied_provider": "random", "resource_type": "random_pet", "resource_name": "animal", "resource_key": null }, "action": "update" }, "type": "resource_drift"} Planned Change[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#planned-change "Direct link to Planned Change") --------------------------------------------------------------------------------------------------------------------------------- At the end of a plan or before an apply, OpenTofu will emit a `planned_change` message for each resource which has changes to apply. This message has an embedded `change` object with the following keys: * `resource`: object describing the address of the resource to be changed; see [resource object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) below for details * `previous_resource`: object describing the previous address of the resource, if this change includes a configuration-driven move * `action`: the action planned to be taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete`, `move`. * `reason`: an optional reason for the change, only used when the action is `replace` or `delete`. Values: * `tainted`: resource was marked as tainted * `requested`: user requested that the resource be replaced, for example via the `-replace` plan flag * `cannot_update`: changes to configuration force the resource to be deleted and created rather than updated * `delete_because_no_resource_config`: no matching resource in configuration * `delete_because_wrong_repetition`: resource instance key has no corresponding `count` or `for_each` in configuration * `delete_because_count_index`: resource instance key is outside the range of the `count` argument * `delete_because_each_key`: resource instance key is not included in the `for_each` argument * `delete_because_no_module`: enclosing module instance is not in configuration This message does not include details about the exact changes which caused the change to be planned. That information is available in [the JSON plan output](https://opentofu.org/docs/v1.11/internals/json-format/) . ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-2 "Direct link to Example") Code Block { "@level": "info", "@message": "random_pet.animal: Plan to create", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.705503-04:00", "change": { "resource": { "addr": "random_pet.animal", "module": "", "resource": "random_pet.animal", "implied_provider": "random", "resource_type": "random_pet", "resource_name": "animal", "resource_key": null }, "action": "create" }, "type": "planned_change"} Change Summary[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#change-summary "Direct link to Change Summary") --------------------------------------------------------------------------------------------------------------------------------- OpenTofu outputs a change summary when a plan or apply operation completes. Both message types include a `changes` object, which has the following keys: * `add`: count of resources to be created (including as part of replacement) * `change`: count of resources to be changed in-place * `remove`: count of resources to be destroyed (including as part of replacement) * `operation`: one of `plan`, `apply`, or `destroy` ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-3 "Direct link to Example") Code Block { "@level": "info", "@message": "Apply complete! Resources: 1 added, 0 changed, 0 destroyed.", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.869168-04:00", "changes": { "add": 1, "change": 0, "remove": 0, "operation": "apply" }, "type": "change_summary"} Outputs[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#outputs "Direct link to Outputs") ------------------------------------------------------------------------------------------------------------ After a successful plan or apply, a message with type `outputs` contains the values of all root module output values. This message contains an `outputs` object, the keys of which are the output names. The outputs values are objects with the following keys: * `action`: for planned outputs, the action which will be taken for the output. Values: `noop`, `create`, `update`, `delete` * `value`: for applied outputs, the value of the output, encoded in JSON * `type`: for applied outputs, the detected HCL type of the output value * `sensitive`: boolean value, `true` if the output is sensitive and should be hidden from UI by default Note that `sensitive` outputs still include the `value` field, and integrating software should respect the sensitivity value as appropriate for the given use case. ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-4 "Direct link to Example") Code Block { "@level": "info", "@message": "Outputs: 1", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.869280-04:00", "outputs": { "pets": { "sensitive": false, "type": "string", "value": "smart-lizard" } }, "type": "outputs"} Operation Messages[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#operation-messages "Direct link to Operation Messages") --------------------------------------------------------------------------------------------------------------------------------------------- Performing OpenTofu operations to a resource will often result in several messages being emitted. The message types include: * `apply_start`: when starting to apply changes for a resource * `apply_progress`: periodically, showing elapsed time output * `apply_complete`: on successful operation completion * `apply_errored`: when an error is encountered during the operation * `provision_start`: when starting a provisioner step * `provision_progress`: on provisioner output * `provision_complete`: on successful provisioning * `provision_errored`: when an error is encountered during provisioning * `refresh_start`: when reading a resource during refresh * `refresh_complete`: on successful refresh Each of these messages has a `hook` object, which has different fields for each type. All hooks have a [`resource` object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) which identifies which resource is the subject of the operation. Apply Start[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#apply-start "Direct link to Apply Start") ------------------------------------------------------------------------------------------------------------------------ The `apply_start` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) identifying the resource * `action`: the action to be taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete` * `id_key` and `id_value`: a key/value pair used to identify this instance of the resource, omitted when unknown ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-5 "Direct link to Example") Code Block { "@level": "info", "@message": "random_pet.animal: Creating...", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.825308-04:00", "hook": { "resource": { "addr": "random_pet.animal", "module": "", "resource": "random_pet.animal", "implied_provider": "random", "resource_type": "random_pet", "resource_name": "animal", "resource_key": null }, "action": "create" }, "type": "apply_start"} Apply Progress[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#apply-progress "Direct link to Apply Progress") --------------------------------------------------------------------------------------------------------------------------------- The `apply_progress` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) identifying the resource * `action`: the action being taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete` * `elapsed_seconds`: time elapsed since the apply operation started, expressed as an integer number of seconds ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-6 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[4]: Still creating... [30s elapsed]", "@module": "tofu.ui", "@timestamp": "2021-03-17T09:34:26.222465-04:00", "hook": { "resource": { "addr": "null_resource.none[4]", "module": "", "resource": "null_resource.none[4]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 4 }, "action": "create", "elapsed_seconds": 30 }, "type": "apply_progress"} Apply Complete[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#apply-complete "Direct link to Apply Complete") --------------------------------------------------------------------------------------------------------------------------------- The `apply_complete` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) identifying the resource * `action`: the action taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete` * `id_key` and `id_value`: a key/value pair used to identify this instance of the resource, omitted when unknown * `elapsed_seconds`: time elapsed since the apply operation started, expressed as an integer number of seconds ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-7 "Direct link to Example") Code Block { "@level": "info", "@message": "random_pet.animal: Creation complete after 0s [id=smart-lizard]", "@module": "tofu.ui", "@timestamp": "2021-05-25T13:32:41.826179-04:00", "hook": { "resource": { "addr": "random_pet.animal", "module": "", "resource": "random_pet.animal", "implied_provider": "random", "resource_type": "random_pet", "resource_name": "animal", "resource_key": null }, "action": "create", "id_key": "id", "id_value": "smart-lizard", "elapsed_seconds": 0 }, "type": "apply_complete"} Apply Errored[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#apply-errored "Direct link to Apply Errored") ------------------------------------------------------------------------------------------------------------------------------ The `apply_complete` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) identifying the resource * `action`: the action taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete` * `elapsed_seconds`: time elapsed since the apply operation started, expressed as an integer number of seconds The exact detail of the error will be rendered as a separate `diagnostic` message. ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-8 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: Creation errored after 10s", "@module": "tofu.ui", "@timestamp": "2021-03-26T16:38:54.013910-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "action": "create", "elapsed_seconds": 10 }, "type": "apply_errored"} Provision Start[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#provision-start "Direct link to Provision Start") ------------------------------------------------------------------------------------------------------------------------------------ The `provision_start` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) identifying the resource * `provisioner`: the type of provisioner ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-9 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: Provisioning with 'local-exec'...", "@module": "tofu.ui", "@timestamp": "2021-03-26T16:38:43.997431-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "provisioner": "local-exec" }, "type": "provision_start"} Provision Progress[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#provision-progress "Direct link to Provision Progress") --------------------------------------------------------------------------------------------------------------------------------------------- The `provision_progress` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) identifying the resource * `provisioner`: the type of provisioner * `output`: the output log from the provisioner One `provision_progress` message is output for each log line received from the provisioner. ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-10 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: (local-exec): Executing: [\"/bin/sh\" \"-c\" \"sleep 10 && exit 1\"]", "@module": "tofu.ui", "@timestamp": "2021-03-26T16:38:43.997869-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "provisioner": "local-exec", "output": "Executing: [\"/bin/sh\" \"-c\" \"sleep 10 && exit 1\"]" }, "type": "provision_progress"} Provision Complete[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#provision-complete "Direct link to Provision Complete") --------------------------------------------------------------------------------------------------------------------------------------------- The `provision_complete` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) identifying the resource * `provisioner`: the type of provisioner ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-11 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: (local-exec) Provisioning complete", "@module": "tofu.ui", "@timestamp": "2021-03-17T09:34:06.239043-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "provisioner": "local-exec" }, "type": "provision_complete"} Provision Errored[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#provision-errored "Direct link to Provision Errored") ------------------------------------------------------------------------------------------------------------------------------------------ The `provision_errored` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) identifying the resource * `provisioner`: the type of provisioner ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-12 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: (local-exec) Provisioning errored", "@module": "tofu.ui", "@timestamp": "2021-03-26T16:38:54.013572-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "provisioner": "local-exec" }, "type": "provision_errored"} Refresh Start[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#refresh-start "Direct link to Refresh Start") ------------------------------------------------------------------------------------------------------------------------------ The `refresh_start` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) identifying the resource * `id_key` and `id_value`: a key/value pair used to identify this instance of the resource ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-13 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: Refreshing state... [id=1971614370559474622]", "@module": "tofu.ui", "@timestamp": "2021-03-26T14:18:06.508915-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "id_key": "id", "id_value": "1971614370559474622" }, "type": "refresh_start"} Refresh Complete[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#refresh-complete "Direct link to Refresh Complete") --------------------------------------------------------------------------------------------------------------------------------------- The `refresh_complete` message `hook` object has the following keys: * `resource`: a [`resource` object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) identifying the resource * `id_key` and `id_value`: a key/value pair used to identify this instance of the resource ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-14 "Direct link to Example") Code Block { "@level": "info", "@message": "null_resource.none[0]: Refresh complete [id=1971614370559474622]", "@module": "tofu.ui", "@timestamp": "2021-03-26T14:18:06.509371-04:00", "hook": { "resource": { "addr": "null_resource.none[0]", "module": "", "resource": "null_resource.none[0]", "implied_provider": "null", "resource_type": "null_resource", "resource_name": "none", "resource_key": 0 }, "id_key": "id", "id_value": "1971614370559474622" }, "type": "refresh_complete"} Resource Object[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object "Direct link to Resource Object") ------------------------------------------------------------------------------------------------------------------------------------ The `resource` object is a decomposed structure representing a resource address in configuration, which is used to identify which resource a given message is associated with. The object has the following keys: * `addr`: the full unique address of the resource as a string * `module`: the address of the module containing the resource, in the form `module.foo.module.bar`, or an empty string for a root module resource * `resource`: the module-relative address, which is identical to `addr` for root module resources * `resource_type`: the type of resource being addressed * `resource_name`: the name label for the resource * `resource_key`: the address key (`count` or `for_each` value), or `null` if the neither are used * `implied_provider`: the provider type implied by the resource type; this may not reflect the resource's provider if provider aliases are used ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-15 "Direct link to Example") Code Block { "addr": "module.pets.random_pet.pet[\"friend\"]", "module": "module.pets", "resource": "random_pet.pet[\"friend\"]", "implied_provider": "random", "resource_type": "random_pet", "resource_name": "pet", "resource_key": "friend"} Test Messages[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#test-messages "Direct link to Test Messages") ------------------------------------------------------------------------------------------------------------------------------ Running OpenTofu tests will result in several messages being emitted. The message types include: * `test_abstract`: Summary of test files and tests found * `test_file`: Summary of test file execution * `test_run`: Summary of test execution * `test_summary`: Summary of overall test file execution status and statistics Test Abstract[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#test-abstract "Direct link to Test Abstract") ------------------------------------------------------------------------------------------------------------------------------ The `test_abstract` message `test_abstract` object contains dynamic keys composed of the test file name: * `main.tftest.hcl`: list of tests found within the test file ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-16 "Direct link to Example") Code Block { "@level": "info", "@message": "Found 1 file and 1 run block", "@module": "tofu.ui", "@timestamp": "2024-04-20T17:24:48.418126+10:00", "test_abstract": { "main.tftest.hcl": [ "test" ] }, "type": "test_abstract"} Test File[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#test-file "Direct link to Test File") ------------------------------------------------------------------------------------------------------------------ The `test_file` message `test_file` object has the following keys: * `path`: the relative path of the test file * `status`: the overall test execution status ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-17 "Direct link to Example") Code Block { "@level": "info", "@message": "main.tftest.hcl... pass", "@module": "tofu.ui", "@testfile": "main.tftest.hcl", "@timestamp": "2024-04-20T17:24:48.588473+10:00", "test_file": { "path": "main.tftest.hcl", "status": "pass" }, "type": "test_file"} Test Run[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#test-run "Direct link to Test Run") --------------------------------------------------------------------------------------------------------------- The `test_run` message `test_run` object has the following keys: * `path`: the relative path of the test file * `run`: name of test that was executed * `status`: the overall test execution status ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-18 "Direct link to Example") Code Block { "@level": "info", "@message": " \"test\"... pass", "@module": "tofu.ui", "@testfile": "main.tftest.hcl", "@testrun": "test", "@timestamp": "2024-04-20T17:24:48.588519+10:00", "test_run": { "path": "main.tftest.hcl", "run": "test", "status": "pass" }, "type": "test_run"} Test Summary[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#test-summary "Direct link to Test Summary") --------------------------------------------------------------------------------------------------------------------------- The `test_summary` message `test_summary` object has the following keys: * `status`: the overall status of all tests executed * `passed`: the total number of tests that passed * `failed`: the total number of tests that failed * `errored`: the total number of tests that errored * `skipped`: the total number of tests that skipped ### Example[​](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-19 "Direct link to Example") Code Block { "@level": "info", "@message": "Success! 1 passed, 0 failed.", "@module": "tofu.ui", "@timestamp": "2024-04-20T17:24:48.716977+10:00", "test_summary": { "status": "pass", "passed": 1, "failed": 0, "errored": 0, "skipped": 0 }, "type": "test_summary"} * [Sample JSON Output](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#sample-json-output) * [Message Types](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#message-types) * [Generic Messages](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#generic-messages) * [Operation Results](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#operation-results) * [Resource Progress](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-progress) * [Version Message](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#version-message) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example) * [Resource Drift](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-drift) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-1) * [Planned Change](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#planned-change) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-2) * [Change Summary](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#change-summary) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-3) * [Outputs](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#outputs) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-4) * [Operation Messages](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#operation-messages) * [Apply Start](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#apply-start) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-5) * [Apply Progress](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#apply-progress) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-6) * [Apply Complete](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#apply-complete) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-7) * [Apply Errored](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#apply-errored) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-8) * [Provision Start](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#provision-start) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-9) * [Provision Progress](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#provision-progress) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-10) * [Provision Complete](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#provision-complete) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-11) * [Provision Errored](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#provision-errored) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-12) * [Refresh Start](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#refresh-start) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-13) * [Refresh Complete](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#refresh-complete) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-14) * [Resource Object](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#resource-object) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-15) * [Test Messages](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#test-messages) * [Test Abstract](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#test-abstract) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-16) * [Test File](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#test-file) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-17) * [Test Run](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#test-run) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-18) * [Test Summary](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#test-summary) * [Example](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/#example-19) --- # Command: env | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/env/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Command: env ============ The `tofu env` command is deprecated. [The `tofu workspace` command](https://opentofu.org/docs/v1.11/cli/commands/workspace/) should be used instead. --- # Command: logout | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/logout/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: logout =============== The `tofu logout` command is used to remove credentials stored by `tofu login`. These credentials are API tokens for any host that offers OpenTofu-compatible services. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/logout/#usage "Direct link to Usage") -------------------------------------------------------------------------------------------- Usage: `tofu logout [hostname]` Note The API token is only removed from local storage, not destroyed on the remote server, so it will remain valid until manually revoked. Credentials Storage[​](https://opentofu.org/docs/v1.11/cli/commands/logout/#credentials-storage "Direct link to Credentials Storage") -------------------------------------------------------------------------------------------------------------------------------------- By default, OpenTofu will remove the token stored in plain text in a local CLI configuration file called `credentials.tfrc.json`. If you have configured a [credentials helper program](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials-helpers) , OpenTofu will use the helper's `forget` command to remove it. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/logout/#usage) * [Credentials Storage](https://opentofu.org/docs/v1.11/cli/commands/logout/#credentials-storage) --- # Files and Directories | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/files/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Files and Directories ===================== File Extension[​](https://opentofu.org/docs/v1.11/language/files/#file-extension "Direct link to File Extension") ------------------------------------------------------------------------------------------------------------------ Code in the OpenTofu language is stored in plain text files with the `.tf` or `.tofu` file extensions. There is also [a JSON-based variant of the language](https://opentofu.org/docs/v1.11/language/syntax/json/) that is named with the `.tf.json` or `.tofu.json` file extensions. Files containing OpenTofu code are often called _configuration files._ ### Extension Precedence[​](https://opentofu.org/docs/v1.11/language/files/#extension-precedence "Direct link to Extension Precedence") When both `.tf` and `.tofu` files with the same base name are present in a directory, OpenTofu will prioritize the `.tofu` file and ignore the `.tf` file. For example: * If both `foo.tf` and `foo.tofu` exist in the same directory, OpenTofu will only load `foo.tofu` and ignore `foo.tf`. This ensures that `.tofu` files always take precedence over `.tf` files when both are available. This scenario can be useful for module authors who want their modules to support both OpenTofu and Terraform. Text Encoding[​](https://opentofu.org/docs/v1.11/language/files/#text-encoding "Direct link to Text Encoding") --------------------------------------------------------------------------------------------------------------- Configuration files must always use UTF-8 encoding, and by convention usually use Unix-style line endings (LF) rather than Windows-style line endings (CRLF), though both are accepted. Directories and Modules[​](https://opentofu.org/docs/v1.11/language/files/#directories-and-modules "Direct link to Directories and Modules") --------------------------------------------------------------------------------------------------------------------------------------------- A _module_ is a collection of one or many `.tf`, `.tf.json`, `.tofu`, `.tofu.json` files kept together in a directory. An OpenTofu module only consists of the top-level configuration files in a directory; nested directories are treated as completely separate modules, and are not automatically included in the configuration. OpenTofu evaluates all of the configuration files in a module, effectively treating the entire module as a single document. Separating various blocks into different files is purely for the convenience of readers and maintainers, and has no effect on the module's behavior. An OpenTofu module can use [module calls](https://opentofu.org/docs/v1.11/language/modules/) to explicitly include other modules into the configuration. These child modules can come from local directories (nested in the parent module's directory, or anywhere else on disk), or from external sources like the [Public OpenTofu Registry](https://registry.opentofu.org/) . The Root Module[​](https://opentofu.org/docs/v1.11/language/files/#the-root-module "Direct link to The Root Module") --------------------------------------------------------------------------------------------------------------------- OpenTofu always runs in the context of a single _root module._ A complete _OpenTofu configuration_ consists of a root module and the tree of child modules (which includes the modules called by the root module, any modules called by those modules, etc.). * In OpenTofu CLI, the root module is the working directory where OpenTofu is invoked. (You can use command line options to specify a root module outside the working directory, but in practice this is rare.) * In [TACOS](https://opentofu.org/docs/v1.11/intro/tacos/) (TF Automation and Collaboration Software), the root module for a workspace defaults to the top level of the configuration directory (supplied via version control repository or direct upload), but the workspace settings can specify a subdirectory to use instead. * [File Extension](https://opentofu.org/docs/v1.11/language/files/#file-extension) * [Extension Precedence](https://opentofu.org/docs/v1.11/language/files/#extension-precedence) * [Text Encoding](https://opentofu.org/docs/v1.11/language/files/#text-encoding) * [Directories and Modules](https://opentofu.org/docs/v1.11/language/files/#directories-and-modules) * [The Root Module](https://opentofu.org/docs/v1.11/language/files/#the-root-module) --- # Attributes as Blocks | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/attr-as-blocks/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Attributes as Blocks ==================== Note This page is an appendix to the OpenTofu documentation. Most users do not need to know the full details of this behavior. Summary[​](https://opentofu.org/docs/v1.11/language/attr-as-blocks/#summary "Direct link to Summary") ------------------------------------------------------------------------------------------------------ Many resource types use repeatable nested blocks to manage collections of sub-objects related to the primary resource. Rarely, some resource types _also_ support an argument with the same name as a nested block type, and will purge any sub-objects of that type if that argument is set to an empty list (` = []`). Most users do not need to know any further details of this "nested block or empty list" behavior. However, read further if you need to: * Use OpenTofu's [JSON syntax](https://opentofu.org/docs/v1.11/language/syntax/json/) with this type of resource. * Create a reusable module that wraps this type of resource. Details[​](https://opentofu.org/docs/v1.11/language/attr-as-blocks/#details "Direct link to Details") ------------------------------------------------------------------------------------------------------ The language makes a distinction between [argument syntax and nested block syntax](https://opentofu.org/docs/v1.11/language/syntax/configuration/#arguments-and-blocks) within blocks: * Argument syntax sets a named argument for the containing object. If the attribute has a default value then an explicitly-specified value entirely overrides that default. * Nested block syntax represents a related child object of the container that has its own set of arguments. Where multiple such objects are possible, multiple blocks of the same type can be present. If the nested attributes themselves have default values, they are honored for each nested block separately, merging in with any explicitly-defined arguments. The distinction between these is particularly important for [JSON syntax](https://opentofu.org/docs/v1.11/language/syntax/json/) because the same primitive JSON constructs (lists and objects) will be interpreted differently depending on whether a particular name is an argument or a nested block type. Defining a Fixed Object Collection Value[​](https://opentofu.org/docs/v1.11/language/attr-as-blocks/#defining-a-fixed-object-collection-value "Direct link to Defining a Fixed Object Collection Value") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When working with resource type arguments that behave in this way, it is valid and we recommend the use of nested block syntax whenever defining a fixed collection of objects: Code Block example { foo = "bar"}example { foo = "baz"} The above implicitly specifies a two-element list of objects assigned to the `example` argument, treating it as if it were a nested block type. If you need to explicitly call for zero `example` objects, you must use the argument syntax with an empty list: Code Block example = [] These two forms cannot be mixed; there cannot be both explicitly zero `example` objects and explicit single `example` blocks declared at the same time. For true nested blocks where this special behavior does not apply, assigning `[]` using argument syntax is not valid. The normal way to specify zero objects of a type is to write no nested blocks at all. Arbitrary Expressions with Argument Syntax[​](https://opentofu.org/docs/v1.11/language/attr-as-blocks/#arbitrary-expressions-with-argument-syntax "Direct link to Arbitrary Expressions with Argument Syntax") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Although we recommend using block syntax for simple cases for readability, the names that work in this mode _are_ defined as arguments, and so it is possible to use argument syntax to assign arbitrary dynamic expressions to them, as long as the expression has the expected result type: Code Block example = [ for name in var.names: { foo = name }] Code Block # Not recommended, but valid: a constant list-of-objects expressionexample = [ { foo = "bar" }, { foo = "baz" },] Because of the rule that argument declarations like this fully override any default value, when creating a list-of-objects expression directly the usual handling of optional arguments does not apply, so all of the arguments must be assigned a value, even if it's an explicit `null`: Code Block example = [ { # Cannot omit foo in this case, even though it would be optional in the # nested block syntax. foo = null },] If you are writing a reusable module that allows callers to pass in a list of objects to assign to such an argument, you may wish to use the `merge` function to populate any attributes the user didn't explicitly set, in order to give the module user the effect of optional arguments: Code Block example = [ for ex in var.examples: merge({ foo = null # (or any other suitable default value) }, ex)] For the arguments that use the attributes-as-blocks usage mode, the above is a better pattern than using [`dynamic` blocks](https://opentofu.org/docs/v1.11/language/expressions/dynamic-blocks/) because the case where the caller provides an empty list will result in explicitly assigning an empty list value, rather than assigning no value at all and thus retaining and ignoring any existing objects. `dynamic` blocks are required for dynamically-generating _normal_ nested blocks, though. In JSON syntax[​](https://opentofu.org/docs/v1.11/language/attr-as-blocks/#in-json-syntax "Direct link to In JSON syntax") --------------------------------------------------------------------------------------------------------------------------- Arguments that use this special mode are specified in JSON syntax always using the [JSON expression mapping](https://opentofu.org/docs/v1.11/language/syntax/json/#expression-mapping) to produce a list of objects. The interpretation of these values in JSON syntax is, therefore, equivalent to that described under _Arbitrary Expressions with Argument Syntax_ above, but expressed in JSON syntax instead. Due to the ambiguity of the JSON syntax, there is no way to distinguish based on the input alone between argument and nested block usage, so the JSON syntax cannot support the nested block processing mode for these arguments. This is, unfortunately, one necessary concession on the equivalence between native syntax and JSON syntax made pragmatically for compatibility with existing provider design patterns. Providers may phase out such patterns in future major releases. * [Summary](https://opentofu.org/docs/v1.11/language/attr-as-blocks/#summary) * [Details](https://opentofu.org/docs/v1.11/language/attr-as-blocks/#details) * [Defining a Fixed Object Collection Value](https://opentofu.org/docs/v1.11/language/attr-as-blocks/#defining-a-fixed-object-collection-value) * [Arbitrary Expressions with Argument Syntax](https://opentofu.org/docs/v1.11/language/attr-as-blocks/#arbitrary-expressions-with-argument-syntax) * [In JSON syntax](https://opentofu.org/docs/v1.11/language/attr-as-blocks/#in-json-syntax) --- # Override Files | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/files/override/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Override Files ============== OpenTofu normally loads all of the `.tf`, `.tofu`, `.tf.json` and `.tofu.json` files within a directory and expects each one to define a distinct set of configuration objects. If two files attempt to define the same object, OpenTofu returns an error. In some rare cases, it is convenient to be able to override specific portions of an existing configuration object in a separate file. For example, a human-edited configuration file in the OpenTofu language native syntax could be partially overridden using a programmatically-generated file in JSON syntax. For these rare situations, OpenTofu has special handling of any configuration file whose name ends in `_override.tf`, `_override.tofu`, `_override.tf.json` or `_override.tofu.json`. This special handling also applies to a file named literally `override.tf`, `override.tofu`, `override.tf.json` or `override.tofu.json`. Note [Extension Precedence](https://opentofu.org/docs/v1.11/language/files/#extension-precedence) is important when dealing with override files. If both `foo_override.tf` and `foo_override.tofu` exist in the same directory, OpenTofu will only load `foo_override.tofu` and disregard `foo_override.tf`. The same rule applies to JSON-based files - if both `foo_override.tofu.json` and `foo_override.tf.json` exist in the same directory, OpenTofu will only load `foo_override.tofu.json` and ignore `foo_override.tf.json`. OpenTofu initially skips these _override files_ when loading configuration, and then afterwards processes each one in turn (in lexicographical order). For each top-level block defined in an override file, OpenTofu attempts to find an already-defined object corresponding to that block and then merges the override block contents into the existing object. Use override files only in special circumstances. Over-use of override files hurts readability, since a reader looking only at the original files cannot easily see that some portions of those files have been overridden without consulting all of the override files that are present. When using override files, use comments in the original files to warn future readers about which override files apply changes to each block. Example[​](https://opentofu.org/docs/v1.11/language/files/override/#example "Direct link to Example") ------------------------------------------------------------------------------------------------------ If you have an OpenTofu configuration `example.tf` with the following contents: Code Block resource "aws_instance" "web" { instance_type = "t2.micro" ami = "ami-408c7f28"} ...and you created a file `override.tf` containing the following: Code Block resource "aws_instance" "web" { ami = "foo"} OpenTofu will merge the latter into the former, behaving as if the original configuration had been as follows: Code Block resource "aws_instance" "web" { instance_type = "t2.micro" ami = "foo"} Merging Behavior[​](https://opentofu.org/docs/v1.11/language/files/override/#merging-behavior "Direct link to Merging Behavior") --------------------------------------------------------------------------------------------------------------------------------- The merging behavior is slightly different for each block type, and some special constructs within certain blocks are merged in a special way. The general rule, which applies in most cases, is: * A top-level block in an override file merges with a block in a normal configuration file that has the same block header. The block _header_ is the block type and any quoted labels that follow it. * Within a top-level block, an attribute argument within an override block replaces any argument of the same name in the original block. * Within a top-level block, any nested blocks within an override block replace _all_ blocks of the same type in the original block. Any block types that do not appear in the override block remain from the original block. * The contents of nested configuration blocks are not merged. * The resulting _merged block_ must still comply with any validation rules that apply to the given block type. If more than one override file defines the same top-level block, the overriding effect is compounded, with later blocks taking precedence over earlier blocks. Overrides are processed in order first by filename (in lexicographical order) and then by position in each file. The following sections describe the special merging behaviors that apply to specific arguments within certain top-level block types. ### Merging `resource` and `data` blocks[​](https://opentofu.org/docs/v1.11/language/files/override/#merging-resource-and-data-blocks "Direct link to merging-resource-and-data-blocks") Within a `resource` block, the contents of any `lifecycle` nested block are merged on an argument-by-argument basis. For example, if an override block sets only the `create_before_destroy` argument then any `ignore_changes` argument in the original block will be preserved. If an overriding `resource` block contains one or more `provisioner` blocks then any `provisioner` blocks in the original block are ignored. If an overriding `resource` block contains a `connection` block then it completely overrides any `connection` block present in the original block. The `depends_on` meta-argument may not be used in override blocks, and will produce an error. ### Merging `variable` blocks[​](https://opentofu.org/docs/v1.11/language/files/override/#merging-variable-blocks "Direct link to merging-variable-blocks") The arguments within a `variable` block are merged in the standard way described above, but some special considerations apply due to the interactions between the `type` and `default` arguments. If the original block defines a `default` value and an override block changes the variable's `type`, OpenTofu attempts to convert the default value to the overridden type, producing an error if this conversion is not possible. Conversely, if the original block defines a `type` and an override block changes the `default`, the overridden default value must be compatible with the original type specification. ### Merging `output` blocks[​](https://opentofu.org/docs/v1.11/language/files/override/#merging-output-blocks "Direct link to merging-output-blocks") The `depends_on` meta-argument may not be used in override blocks, and will produce an error. ### Merging `locals` blocks[​](https://opentofu.org/docs/v1.11/language/files/override/#merging-locals-blocks "Direct link to merging-locals-blocks") Each `locals` block defines a number of named values. Overrides are applied on a value-by-value basis, ignoring which `locals` block they are defined in. ### Merging `terraform` blocks[​](https://opentofu.org/docs/v1.11/language/files/override/#merging-terraform-blocks "Direct link to merging-terraform-blocks") The settings within `terraform` blocks are considered individually when merging. If the `required_providers` argument is set, its value is merged on an element-by-element basis, which allows an override block to adjust the constraint for a single provider without affecting the constraints for other providers. In both the `required_version` and `required_providers` settings, each override constraint entirely replaces the constraints for the same component in the original block. If both the base block and the override block both set `required_version` then the constraints in the base block are entirely ignored. The presence of a block defining a backend (either `cloud` or `backend`) in an override file always takes precedence over a block defining a backend in the original configuration. That is, if a `cloud` block is set within the original configuration and a `backend` block is set in the override file, OpenTofu will use the `backend` block specified in the override file upon merging. Similarly, if a `backend` block is set within the original configuration and a `cloud` block is set in the override file, OpenTofu will use the `cloud` block specified in the override file upon merging. * [Example](https://opentofu.org/docs/v1.11/language/files/override/#example) * [Merging Behavior](https://opentofu.org/docs/v1.11/language/files/override/#merging-behavior) * [Merging `resource` and `data` blocks](https://opentofu.org/docs/v1.11/language/files/override/#merging-resource-and-data-blocks) * [Merging `variable` blocks](https://opentofu.org/docs/v1.11/language/files/override/#merging-variable-blocks) * [Merging `output` blocks](https://opentofu.org/docs/v1.11/language/files/override/#merging-output-blocks) * [Merging `locals` blocks](https://opentofu.org/docs/v1.11/language/files/override/#merging-locals-blocks) * [Merging `terraform` blocks](https://opentofu.org/docs/v1.11/language/files/override/#merging-terraform-blocks) --- # Command: login | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/login/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: login ============== The `tofu login` command can be used to automatically obtain and save an API token for any host that offers OpenTofu-compatible services. Note This command is suitable only for use in interactive scenarios where it is possible to launch a web browser on the same host where OpenTofu is running. If you are running OpenTofu in an unattended automation scenario, you can [configure credentials manually in the CLI configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials) . Usage[​](https://opentofu.org/docs/v1.11/cli/commands/login/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------- Usage: `tofu login [hostname]` Credentials Storage[​](https://opentofu.org/docs/v1.11/cli/commands/login/#credentials-storage "Direct link to Credentials Storage") ------------------------------------------------------------------------------------------------------------------------------------- By default, OpenTofu will obtain an API token and save it in plain text in a local CLI configuration file called `credentials.tfrc.json`. When you run `tofu login`, it will explain specifically where it intends to save the API token and give you a chance to cancel if the current configuration is not as desired. If you don't wish to store your API token in the default location, you can optionally configure a [credentials helper program](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials-helpers) which knows how to store and later retrieve credentials in some other system, such as your organization's existing secrets management system. Login Server Support[​](https://opentofu.org/docs/v1.11/cli/commands/login/#login-server-support "Direct link to Login Server Support") ---------------------------------------------------------------------------------------------------------------------------------------- The `tofu login` command works with any server supporting the [login protocol](https://opentofu.org/docs/v1.11/internals/login-protocol/) . * [Usage](https://opentofu.org/docs/v1.11/cli/commands/login/#usage) * [Credentials Storage](https://opentofu.org/docs/v1.11/cli/commands/login/#credentials-storage) * [Login Server Support](https://opentofu.org/docs/v1.11/cli/commands/login/#login-server-support) --- # Command: fmt | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/fmt/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: fmt ============ The `tofu fmt` command is used to rewrite OpenTofu configuration files to a canonical format and style. This command applies a subset of the [OpenTofu language style conventions](https://opentofu.org/docs/v1.11/language/syntax/style/) , along with other minor adjustments for readability. Other OpenTofu commands that generate OpenTofu configuration will produce configuration files that conform to the style imposed by `tofu fmt`, so using this style in your own files will ensure consistency. The canonical format may change in minor ways between OpenTofu versions, so after upgrading OpenTofu we recommend to proactively run `tofu fmt` on your modules along with any other changes you are making to adopt the new version. We don't consider new formatting rules in `tofu fmt` to be a breaking change in new versions of OpenTofu, but we do aim to minimize changes for configurations that are already following the style examples shown in the OpenTofu documentation. When adding new formatting rules, they will usually aim to apply more of the rules already shown in the configuration examples in the documentation, and so we recommend following the documented style even for decisions that `tofu fmt` doesn't yet apply automatically. Formatting decisions are always subjective and so you might disagree with the decisions that `tofu fmt` makes. This command is intentionally opinionated and has no customization options because its primary goal is to encourage consistency of style between different OpenTofu codebases, even though the chosen style can never be everyone's favorite. We recommend that you follow the style conventions applied by `tofu fmt` when writing OpenTofu modules, but if you find the results particularly objectionable then you may choose not to use this command, and possibly choose to use a third-party formatting tool instead. If you choose to use a third-party tool then you should also run it on files that are generated automatically by OpenTofu, to get consistency between your hand-written files and the generated files. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/fmt/#usage "Direct link to Usage") ----------------------------------------------------------------------------------------- Usage: `tofu fmt [options] [target...]` By default, `fmt` scans the current directory for configuration files. If you provide a directory for the `target` argument, then `fmt` will scan that directory instead. If you provide a file, then `fmt` will process just that file. If you provide a single dash (`-`), then `fmt` will read from standard input (STDIN). The command-line flags are all optional. The following flags are available: * `-list=false` - Don't list the files containing formatting inconsistencies. * `-write=false` - Don't overwrite the input files. (This is implied by `-check` or when the input is STDIN.) * `-diff` - Display diffs of formatting changes. * When using this flag, ensure that `diff` tool is installed. This is used internally for providing a better user experience. * `-check` - Check if the input is formatted. Exit status will be 0 if all input is properly formatted. If not, exit status will be non-zero and the command will output a list of filenames whose files are not properly formatted. * `-recursive` - Also process files in subdirectories. By default, only the given directory (or current directory) is processed. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/fmt/#usage) --- # Command: force-unlock | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/force-unlock/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: force-unlock ===================== Manually unlock the state for the defined configuration. This will not modify your infrastructure. This command removes the lock on the state for the current configuration. The behavior of this lock is dependent on the backend being used. Local state files cannot be unlocked by another process. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/force-unlock/#usage "Direct link to Usage") -------------------------------------------------------------------------------------------------- Usage: `tofu force-unlock [options] LOCK_ID` Manually unlock the state for the defined configuration. This will not modify your infrastructure. This command removes the lock on the state for the current configuration. The behavior of this lock is dependent on the backend being used. Local state files cannot be unlocked by another process. Note Use of variables in [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu force-unlock`. Options: * `-force` - Don't ask for input for unlock confirmation. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/force-unlock/#usage) --- # Command: destroy | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/destroy/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: destroy ================ The `tofu destroy` command is a convenient way to destroy all remote objects managed by a particular OpenTofu configuration. While you will typically not want to destroy long-lived objects in a production environment, OpenTofu is sometimes used to manage ephemeral infrastructure for development purposes, in which case you can use `tofu destroy` to conveniently clean up all of those temporary objects once you are finished with your work. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/destroy/#usage "Direct link to Usage") --------------------------------------------------------------------------------------------- Usage: `tofu destroy [options]` This command is just a convenience alias for the following command: Code Block tofu apply -destroy For that reason, this command accepts most of the options that [`tofu apply`](https://opentofu.org/docs/v1.11/cli/commands/apply/) accepts, although it does not accept a plan file argument and forces the selection of the "destroy" planning mode. You can also create a speculative destroy plan, to see what the effect of destroying would be, by running the following command: Code Block tofu plan -destroy This will run [`tofu plan`](https://opentofu.org/docs/v1.11/cli/commands/plan/) in _destroy_ mode, showing you the proposed destroy changes without executing them. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/destroy/#usage) --- # Checks | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/checks/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Checks ====== The `check` block can validate your infrastructure outside the usual resource lifecycle. Check blocks address a gap between post-apply and functional validation of infrastructure. Check blocks allow you to define [custom conditions](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/) that execute on every OpenTofu plan or apply operation without affecting the overall status of an operation. Check blocks execute as the last step of a plan or apply after OpenTofu has planned or provisioned your infrastructure. Syntax[​](https://opentofu.org/docs/v1.11/language/checks/#syntax "Direct link to Syntax") ------------------------------------------------------------------------------------------- You can declare a `check` block with a local name, zero-to-one scoped [data sources](https://opentofu.org/docs/v1.11/language/checks/#scoped-data-sources) , and one-to-many [assertions](https://opentofu.org/docs/v1.11/language/checks/#assertions) . The following example loads the website and validates that it returns the expected status code `200`. Code Block check "health_check" { data "http" "opentofu_org" { url = "https://www.opentofu.org" } assert { condition = data.http.opentofu_org.status_code == 200 error_message = "${data.http.opentofu_org.url} returned an unhealthy status code" }} ### Scoped data sources[​](https://opentofu.org/docs/v1.11/language/checks/#scoped-data-sources "Direct link to Scoped data sources") You can use any data source from any provider as a scoped data source within a `check` block. A `check` block can optionally contain a nested (a.k.a. scoped) data source. This `data` block behaves like an external [data source](https://opentofu.org/docs/v1.11/language/data-sources/) , except you can not reference it outside its enclosing `check` block. Additionally, if a scoped data source's provider raises any errors, they are masked as warnings and do not prevent OpenTofu from continuing operation execution. You can use a scoped data source to validate the status of a piece of infrastructure outside of the usual OpenTofu resource lifecycle. [In the above example](https://opentofu.org/docs/v1.11/language/checks/#syntax) , if the `opentofu_org` data source fails to load, you receive a warning instead of a blocking error, which would occur if you declared this data source outside of a `check` block. #### Meta-Arguments[​](https://opentofu.org/docs/v1.11/language/checks/#meta-arguments "Direct link to Meta-Arguments") Scoped data sources support the `depends_on` and `provider` [meta-arguments](https://opentofu.org/docs/v1.11/language/resources/syntax/#meta-arguments) . Scoped data sources do not support the `count` or`for_each` meta-arguments. ##### `depends_on`[​](https://opentofu.org/docs/v1.11/language/checks/#depends_on "Direct link to depends_on") The `depends_on` meta-argument can be particularly powerful when used within scoped data sources. The first time OpenTofu creates the _initial_ plan for our [previous example](https://opentofu.org/docs/v1.11/language/checks/#syntax) , the plan fails because OpenTofu has not applied its configuration yet. Meaning this test fails because OpenTofu must still create the resources to make this website exist. Therefore, the first time OpenTofu runs this check, it always throws a potentially distracting error message. You can fix this by adding [`depends_on`](https://opentofu.org/docs/v1.11/language/meta-arguments/depends_on/) to your scoped data source, ensuring it depends on an essential piece of your site's infrastructure, such as the load balancer. The check returns `known after apply` until that crucial piece of your website is ready. This strategy avoids producing unnecessary warnings during setup, and the check executes during subsequent plans and applies. One problem with this strategy is that if the resource your scoped data source `depends_on` changes, the check block returns `known after apply` until OpenTofu has updated that resource. Depending on your use case, this behavior could be acceptable or problematic. We recommend implementing the `depends_on` meta-argument if your scoped data source depends on the existence of another resource without referencing it directly. ### Assertions[​](https://opentofu.org/docs/v1.11/language/checks/#assertions "Direct link to Assertions") Check blocks validate your custom assertions using `assert` blocks. Each `check` block must have at least one, but potentially many, `assert` blocks. Each `assert` block has a [`condition` attribute](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/#condition-expressions) and an [`error_message` attribute](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/#error-messages) . Unlike other [custom conditions](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/) , assertions do not affect OpenTofu's execution of an operation. A failed assertion reports a warning without halting the ongoing operation. This contrasts with other custom conditions, such as a postcondition, where OpenTofu produces an error immediately, halting the operation and blocking the application or planning of future resources. Condition arguments within `assert` blocks can refer to scoped data sources within the enclosing `check` block and any variables, resources, data sources, or module outputs within the current module. [Learn more about assertions](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/#checks-with-assertions) . ### Meta-Arguments[​](https://opentofu.org/docs/v1.11/language/checks/#meta-arguments-1 "Direct link to Meta-Arguments") Check blocks do not currently support [meta-arguments](https://opentofu.org/docs/v1.11/language/resources/syntax/#meta-arguments) . We are still collecting feedback on this feature, so if your use case would benefit from check blocks supporting meta-arguments, please [let us know](https://github.com/opentofu/opentofu/issues/new/choose) . Continuous validation in TACOS (TF Automation and Collaboration Software)[​](https://opentofu.org/docs/v1.11/language/checks/#continuous-validation-in-tacos-tf-automation-and-collaboration-software "Direct link to Continuous validation in TACOS (TF Automation and Collaboration Software)") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [TACOS](https://opentofu.org/docs/v1.11/intro/tacos/) (TF Automation and Collaboration Software) can automatically validate whether checks in a workspace’s configuration continue to pass after OpenTofu provisions new infrastructure. Choosing Checks or other Custom Conditions[​](https://opentofu.org/docs/v1.11/language/checks/#choosing-checks-or-other-custom-conditions "Direct link to Choosing Checks or other Custom Conditions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Check blocks offer the most _flexible_ validation solution within OpenTofu. You can reference outputs, variables, resources, and data sources within check assertions. You can also use checks to model every alternate [Custom Condition](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/) . However, that does not mean you should replace all your custom conditions with check blocks. There are major behavioral differences between check block assertions and other custom conditions, the main one being that check blocks do _not_ affect OpenTofu's execution of an operation. You can use this non-blocking behavior to decide the best type of validation for your use case. ### Outputs and variables[​](https://opentofu.org/docs/v1.11/language/checks/#outputs-and-variables "Direct link to Outputs and variables") [Output postconditions](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/#outputs) and [variable validations](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/#input-variable-validation) both make assertions around inputs and outputs. This is one of the cases where you might want OpenTofu to block further execution. For example, it is not helpful for OpenTofu to warn that an input variable is invalid after it applies an entire configuration with that input variable. In this case, a check block would warn of the invalid input variable _without_ interrupting the operation. A validation block for the same input variable would alert you of the invalid variable and halt the plan or apply operation. ### Resource Preconditions and Postconditions[​](https://opentofu.org/docs/v1.11/language/checks/#resource-preconditions-and-postconditions "Direct link to Resource Preconditions and Postconditions") The difference between [preconditions and postconditions](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/#preconditions-and-postconditions) and check blocks is more nuanced. Preconditions are unique amongst the custom conditions in that they execute _before_ a resource change is applied or planned. [Choosing Between Preconditions and Postconditions](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/#choosing-between-preconditions-and-postconditions) offers guidance on choosing between a precondition and a postcondition, and the same topics also apply to choosing between a precondition and a check block. You can often use postconditions interchangeably with check blocks to validate resources and data sources. For example, you can [rewrite the above `check` block example](https://opentofu.org/docs/v1.11/language/checks/#syntax) to use a postcondition instead. The below code uses a `postcondition` block to validate that the website returns the expected status code of `200`. Code Block data "http" "opentofu_org" { url = "https://www.opentofu.org" lifecycle { postcondition { condition = self.status_code == 200 error_message = "${self.url} returned an unhealthy status code" } }} Both the `check` and `postcondition` block examples validate that the website returns a `200` status code during a plan or an apply operation. The difference between the two blocks is how each handles failure. If a `postcondition` block fails, it _blocks_ OpenTofu from executing the current operation. If a `check` block fails, it _does not_ block OpenTofu from executing an operation. If the above example's postcondition fails, it is impossible to recover from. OpenTofu blocks any future plan or apply operations if your postcondition is unsatisfied during the planning stage. This problem occurs because the postcondition does not directly depend on OpenTofu configuration, but instead on the complex interactions between multiple resources. We recommend using check blocks to validate the status of infrastructure as a whole. We only recommend using postconditions when you want a guarantee on a single resource based on that resource's configuration. * [Syntax](https://opentofu.org/docs/v1.11/language/checks/#syntax) * [Scoped data sources](https://opentofu.org/docs/v1.11/language/checks/#scoped-data-sources) * [Assertions](https://opentofu.org/docs/v1.11/language/checks/#assertions) * [Meta-Arguments](https://opentofu.org/docs/v1.11/language/checks/#meta-arguments-1) * [Continuous validation in TACOS (TF Automation and Collaboration Software)](https://opentofu.org/docs/v1.11/language/checks/#continuous-validation-in-tacos-tf-automation-and-collaboration-software) * [Choosing Checks or other Custom Conditions](https://opentofu.org/docs/v1.11/language/checks/#choosing-checks-or-other-custom-conditions) * [Outputs and variables](https://opentofu.org/docs/v1.11/language/checks/#outputs-and-variables) * [Resource Preconditions and Postconditions](https://opentofu.org/docs/v1.11/language/checks/#resource-preconditions-and-postconditions) --- # Command: get | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/get/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: get ============ The `tofu get` command is used to download and update [modules](https://opentofu.org/docs/v1.11/language/modules/develop/) mentioned in the root module. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/get/#usage "Direct link to Usage") ----------------------------------------------------------------------------------------- Usage: `tofu get [options]` The modules are downloaded into a `.terraform` subdirectory of the current working directory. Don't commit this directory to your version control repository. Note Use of [variables in module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu get`. The `get` command supports the following option: * `-update` - If specified, modules that are already downloaded will be checked for updates and the updates will be downloaded if present. * `-no-color` - Disable text coloring in the output. * `-json` Produce output in a machine-readable JSON format, suitable for use in text editor integrations and other automated systems. Always disables color. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/get/#usage) --- # Basic CLI Features | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Basic CLI Features ================== The command line interface to OpenTofu is the `tofu` command, which accepts a variety of subcommands such as `tofu init` or `tofu plan`. To view a list of the commands available in your current OpenTofu version, run `tofu` with no additional arguments: Code Block Usage: tofu [global options] [args]The available commands for execution are listed below.The primary workflow commands are given first, followed byless common or more advanced commands.Main commands: init Prepare your working directory for other commands validate Check whether the configuration is valid plan Show changes required by the current configuration apply Create or update infrastructure destroy Destroy previously-created infrastructureAll other commands: console Try OpenTofu expressions at an interactive command prompt fmt Reformat your configuration in the standard style force-unlock Release a stuck lock on the current workspace get Install or upgrade remote OpenTofu modules graph Generate a Graphviz graph of the steps in an operation import Associate existing infrastructure with a OpenTofu resource login Obtain and save credentials for a remote host logout Remove locally-stored credentials for a remote host metadata Metadata related commands output Show output values from your root module providers Show the providers required for this configuration refresh Update the state to match remote systems show Show the current state or a saved plan state Advanced state management taint Mark a resource instance as not fully functional untaint Remove the 'tainted' state from a resource instance version Show the current OpenTofu version workspace Workspace managementGlobal options (use these before the subcommand, if any): -chdir=DIR Switch to a different working directory before executing the given subcommand. -help Show this help output, or the help for a specified subcommand. -version An alias for the "version" subcommand. (The output from your current OpenTofu version may be different than the above example.) To get specific help for any specific command, use the `-help` option with the relevant subcommand. For example, to see help about the "validate" subcommand you can run `tofu validate -help`. The inline help built in to OpenTofu CLI describes the most important characteristics of each command. For more detailed information, refer to each command's page for details. Switching working directory with `-chdir`[​](https://opentofu.org/docs/v1.11/cli/commands/#switching-working-directory-with--chdir "Direct link to switching-working-directory-with--chdir") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The usual way to run OpenTofu is to first switch to the directory containing the `.tf` or `.tofu` files for your root module (for example, using the `cd` command), so that OpenTofu will find those files automatically without any extra arguments. In some cases though β€” particularly when wrapping OpenTofu in automation scripts β€” it can be convenient to run OpenTofu from a different directory than the root module directory. To allow that, OpenTofu supports a global option `-chdir=...` which you can include before the name of the subcommand you intend to run: Code Block tofu -chdir=environments/production apply The `chdir` option instructs OpenTofu to change its working directory to the given directory before running the given subcommand. This means that any files that OpenTofu would normally read or write in the current working directory will be read or written in the given directory instead. There are two exceptions where OpenTofu will use the original working directory even when you specify `-chdir=...`: * Settings in the [CLI Configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/) are not for a specific subcommand and OpenTofu processes them before acting on the `-chdir` option. * In case you need to use files from the original working directory as part of your configuration, a reference to `path.cwd` in the configuration will produce the original working directory instead of the overridden working directory. Use `path.root` to get the root module directory. Shell Tab-completion[​](https://opentofu.org/docs/v1.11/cli/commands/#shell-tab-completion "Direct link to Shell Tab-completion") ---------------------------------------------------------------------------------------------------------------------------------- If you use either `bash` or `zsh` as your command shell, OpenTofu can provide tab-completion support for all command names and some command arguments. To add the necessary commands to your shell profile, run the following command: Code Block tofu -install-autocomplete After installation, it is necessary to restart your shell or to re-read its profile script before completion will be activated. To uninstall the completion hook, assuming that it has not been modified manually in the shell profile, run the following command: Code Block tofu -uninstall-autocomplete * [Switching working directory with `-chdir`](https://opentofu.org/docs/v1.11/cli/commands/#switching-working-directory-with--chdir) * [Shell Tab-completion](https://opentofu.org/docs/v1.11/cli/commands/#shell-tab-completion) --- # Data Sources | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/data-sources/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Data Sources ============ _Data sources_ allow OpenTofu to use information defined outside of OpenTofu, defined by another separate OpenTofu configuration, or modified by functions. Each [provider](https://opentofu.org/docs/v1.11/language/providers/) may offer data sources alongside its set of [resource](https://opentofu.org/docs/v1.11/language/resources/) types. Using Data Sources[​](https://opentofu.org/docs/v1.11/language/data-sources/#using-data-sources "Direct link to Using Data Sources") ------------------------------------------------------------------------------------------------------------------------------------- A data source is accessed via a special kind of resource known as a _data resource_, declared using a `data` block: Code Block data "aws_ami" "example" { most_recent = true owners = ["self"] tags = { Name = "app-server" Tested = "true" }} A `data` block requests that OpenTofu read from a given data source ("aws\_ami") and export the result under the given local name ("example"). The name is used to refer to this resource from elsewhere in the same OpenTofu module, but has no significance outside of the scope of a module. The data source and name together serve as an identifier for a given resource and so must be unique within a module. Within the block body (between `{` and `}`) are query constraints defined by the data source. Most arguments in this section depend on the data source, and indeed in this example `most_recent`, `owners` and `tags` are all arguments defined specifically for [the `aws_ami` data source](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) . When distinguishing from data resources, the primary kind of resource (as declared by a `resource` block) is known as a _managed resource_. Both kinds of resources take arguments and export attributes for use in configuration, but while managed resources cause OpenTofu to create, update, and delete infrastructure objects, data resources cause OpenTofu only to _read_ objects. For brevity, managed resources are often referred to just as "resources" when the meaning is clear from context. Data Source Arguments[​](https://opentofu.org/docs/v1.11/language/data-sources/#data-source-arguments "Direct link to Data Source Arguments") ---------------------------------------------------------------------------------------------------------------------------------------------- Each data resource is associated with a single data source, which determines the kind of object (or objects) it reads and what query constraint arguments are available. Each data source in turn belongs to a [provider](https://opentofu.org/docs/v1.11/language/providers/) , which is a plugin for OpenTofu that offers a collection of resource types and data sources that most often belong to a single cloud or on-premises infrastructure platform. Most of the items within the body of a `data` block are defined by and specific to the selected data source, and these arguments can make full use of [expressions](https://opentofu.org/docs/v1.11/language/expressions/) and other dynamic OpenTofu language features. However, there are some [meta-arguments](https://opentofu.org/docs/v1.11/language/data-sources/#meta-arguments) that are defined by OpenTofu itself and apply across all data resource types. These arguments often have additional restrictions on what language features can be used with them, and are described in more detail in the following sections. Data Resource Behavior[​](https://opentofu.org/docs/v1.11/language/data-sources/#data-resource-behavior "Direct link to Data Resource Behavior") ------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu reads data resources during the planning phase when possible, but announces in the plan when it must defer reading resources until the apply phase to preserve the order of operations. OpenTofu defers reading data resources in the following situations: * At least one of the given arguments is a managed resource attribute or other value that OpenTofu cannot predict until the apply step. * The data resource depends directly on a managed resource that itself has planned changes in the current plan. * The data resource has [custom conditions](https://opentofu.org/docs/v1.11/language/data-sources/#custom-condition-checks) and it depends directly or indirectly on a managed resource that itself has planned changes in the current plan. Refer to [Data Resource Dependencies](https://opentofu.org/docs/v1.11/language/data-sources/#data-resource-dependencies) for details on what it means for a data resource to depend on other objects. Any resulting attribute of such a data resource will be unknown during planning, so it cannot be used in situations where values must be fully known. Meta-Arguments[​](https://opentofu.org/docs/v1.11/language/data-sources/#meta-arguments "Direct link to Meta-Arguments") ------------------------------------------------------------------------------------------------------------------------- The OpenTofu language defines several meta-arguments, which can be used with any data resource type to change the behavior of resources. The following meta-arguments are documented on separate pages: * [`depends_on`, for specifying hidden dependencies](https://opentofu.org/docs/v1.11/language/meta-arguments/depends_on/) * [`enabled`, for creating conditionally single-resource instances according to a expression](https://opentofu.org/docs/v1.11/language/meta-arguments/enabled/) * [`count`, for creating multiple resource instances according to a count](https://opentofu.org/docs/v1.11/language/meta-arguments/count/) * [`for_each`, to create multiple instances according to a map, or set of strings](https://opentofu.org/docs/v1.11/language/meta-arguments/for_each/) * [`provider`, for selecting a non-default provider configuration](https://opentofu.org/docs/v1.11/language/meta-arguments/resource-provider/) * [`lifecycle`, for lifecycle customizations](https://opentofu.org/docs/v1.11/language/data-sources/#lifecycle-customizations) Lifecycle Customizations[​](https://opentofu.org/docs/v1.11/language/data-sources/#lifecycle-customizations "Direct link to Lifecycle Customizations") ------------------------------------------------------------------------------------------------------------------------------------------------------- A `lifecycle` block inside a `data` block allows some customization of OpenTofu's behavior relating to instances of a resource at different phases of its lifecycle. Code Block data "example" "example" { # ...normal resource arguments... lifecycle { # ...lifecycle arguments... }} The following arguments and nested block types are supported in the `lifecycle` block for a data resource: * `enabled` (bool) - Controls whether the data resource will be read by OpenTofu. When set to `false`, the resource is excluded from the configuration as if it didn't exist. When set to `true` (the default), the resource operates normally. For more information, refer to [the `enabled` meta-argument](https://opentofu.org/docs/v1.11/language/meta-arguments/enabled/) . * `precondition` and `postcondition` blocks, as described in [Custom Conditions](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/#preconditions-and-postconditions) . Local-only Data Sources[​](https://opentofu.org/docs/v1.11/language/data-sources/#local-only-data-sources "Direct link to Local-only Data Sources") ---------------------------------------------------------------------------------------------------------------------------------------------------- While many data sources correspond to an infrastructure object type that is accessed via a remote network API, some specialized data sources operate only within OpenTofu itself, calculating some results and exposing them for use elsewhere. For example, local-only data sources exist for [rendering templates](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) , [reading local files](https://registry.terraform.io/providers/hashicorp/local/latest/docs/data-sources/file) , and [rendering AWS IAM policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) . The behavior of local-only data sources is the same as all other data sources, but their result data exists only temporarily during an OpenTofu operation, and is re-calculated each time a new plan is created. Data Resource Dependencies[​](https://opentofu.org/docs/v1.11/language/data-sources/#data-resource-dependencies "Direct link to Data Resource Dependencies") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Data resources have the same dependency resolution behavior [as defined for managed resources](https://opentofu.org/docs/v1.11/language/resources/behavior/#resource-dependencies) . Setting the `depends_on` meta-argument within `data` blocks defers reading of the data source until after all changes to the dependencies have been applied. In order to ensure that data sources are accessing the most up to date information possible in a wide variety of use cases, arguments directly referencing managed resources are treated the same as if the resource was listed in `depends_on`. This behavior can be avoided when desired by indirectly referencing the managed resource values through a `local` value, unless the data resource itself has [custom conditions](https://opentofu.org/docs/v1.11/language/data-sources/#custom-condition-checks) . Custom Condition Checks[​](https://opentofu.org/docs/v1.11/language/data-sources/#custom-condition-checks "Direct link to Custom Condition Checks") ---------------------------------------------------------------------------------------------------------------------------------------------------- You can use `precondition` and `postcondition` blocks to specify assumptions and guarantees about how the data source operates. The following examples creates a postcondition that checks whether the AMI has the correct tags. Code Block data "aws_ami" "example" { id = var.aws_ami_id lifecycle { # The AMI ID must refer to an existing AMI that has the tag "nomad-server". postcondition { condition = self.tags["Component"] == "nomad-server" error_message = "tags[\"Component\"] must be \"nomad-server\"." } }} Custom conditions can help capture assumptions, helping future maintainers understand the configuration design and intent. They also return useful information about errors earlier and in context, helping consumers more easily diagnose issues in their configurations. Refer to [Custom Condition Checks](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/#preconditions-and-postconditions) for more details. ### Non-Default Provider Configurations[​](https://opentofu.org/docs/v1.11/language/data-sources/#non-default-provider-configurations "Direct link to Non-Default Provider Configurations") Similarly to [resources](https://opentofu.org/docs/v1.11/language/resources/) , when a module has multiple configurations for the same provider you can specify which configuration to use with the `provider` meta-argument: Code Block data "aws_ami" "web" { provider = aws.west # ...} See [The Resource `provider` Meta-Argument](https://opentofu.org/docs/v1.11/language/meta-arguments/resource-provider/) for more information. * [Using Data Sources](https://opentofu.org/docs/v1.11/language/data-sources/#using-data-sources) * [Data Source Arguments](https://opentofu.org/docs/v1.11/language/data-sources/#data-source-arguments) * [Data Resource Behavior](https://opentofu.org/docs/v1.11/language/data-sources/#data-resource-behavior) * [Meta-Arguments](https://opentofu.org/docs/v1.11/language/data-sources/#meta-arguments) * [Lifecycle Customizations](https://opentofu.org/docs/v1.11/language/data-sources/#lifecycle-customizations) * [Local-only Data Sources](https://opentofu.org/docs/v1.11/language/data-sources/#local-only-data-sources) * [Data Resource Dependencies](https://opentofu.org/docs/v1.11/language/data-sources/#data-resource-dependencies) * [Custom Condition Checks](https://opentofu.org/docs/v1.11/language/data-sources/#custom-condition-checks) * [Non-Default Provider Configurations](https://opentofu.org/docs/v1.11/language/data-sources/#non-default-provider-configurations) --- # Command: graph | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/graph/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: graph ============== The `tofu graph` command is used to generate a visual representation of either a configuration or execution plan. The output is in the DOT format, which can be used by [GraphViz](http://www.graphviz.org/) to generate charts. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/graph/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------- Usage: `tofu graph [options]` Outputs the visual execution graph of OpenTofu resources according to either the current configuration or an execution plan. The graph is outputted in DOT format. The typical program that can read this format is GraphViz, but many web services are also available to read this format. The `-type` flag can be used to control the type of graph shown. OpenTofu creates different graphs for different operations. See the options below for the list of types supported. The default type is "plan" if a configuration is given, and "apply" if a plan file is passed as an argument. Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu graph`. Options: * `-plan=tfplan` - Render graph using the specified plan file instead of the configuration in the current directory. * `-draw-cycles` - Highlight any cycles in the graph with colored edges. This helps when diagnosing cycle errors. * `-type=plan` - Type of graph to output. Can be: `plan`, `plan-refresh-only`, `plan-destroy`, or `apply`. * `-module-depth=n` - (deprecated) In prior versions of OpenTofu, specified the depth of modules to show in the output. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. Generating Images[​](https://opentofu.org/docs/v1.11/cli/commands/graph/#generating-images "Direct link to Generating Images") ------------------------------------------------------------------------------------------------------------------------------- The output of `tofu graph` is in the DOT format, which can easily be converted to an image by making use of `dot` provided by GraphViz: Code Block $ tofu graph | dot -Tsvg > graph.svg Here is an example graph output: ![Graph Example](https://opentofu.org/assets/images/graph-example-2cb670610fca15c115d0e2432c41a241.png) * [Usage](https://opentofu.org/docs/v1.11/cli/commands/graph/#usage) * [Generating Images](https://opentofu.org/docs/v1.11/cli/commands/graph/#generating-images) --- # Command: workspace | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/workspace/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: workspace ================== The `tofu workspace` command is used to manage [workspaces](https://opentofu.org/docs/v1.11/language/state/workspaces/) . This command is a container for further subcommands that each have their own page in the documentation. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/workspace/#usage "Direct link to Usage") ----------------------------------------------------------------------------------------------- Usage: `tofu workspace [options] [args]` Choose a subcommand page for more information. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/workspace/#usage) --- # Command: state | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/state/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state ============== The `tofu state` command is used for advanced state management. As your OpenTofu usage becomes more advanced, there are some cases where you may need to modify the [OpenTofu state](https://opentofu.org/docs/v1.11/language/state/) . Rather than modify the state directly, the `tofu state` commands can be used in many cases instead. This command is a nested subcommand, meaning that it has further subcommands. These subcommands are listed to the left. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/state/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------- Usage: `tofu state [options] [args]` Please click a subcommand to the left for more information. Remote State[​](https://opentofu.org/docs/v1.11/cli/commands/state/#remote-state "Direct link to Remote State") ---------------------------------------------------------------------------------------------------------------- The OpenTofu state subcommands all work with remote state just as if it was local state. Reads and writes may take longer than normal as each read and each write do a full network roundtrip. Otherwise, backups are still written to disk and the CLI usage is the same as if it were local state. Backups[​](https://opentofu.org/docs/v1.11/cli/commands/state/#backups "Direct link to Backups") ------------------------------------------------------------------------------------------------- All `tofu state` subcommands that modify the state write backup files. The path of these backup file can be controlled with `-backup`. Subcommands that are read-only (such as [list](https://opentofu.org/docs/v1.11/cli/commands/state/list/) ) do not write any backup files since they aren't modifying the state. Note that backups for state modification _can not be disabled_. Due to the sensitivity of the state file, OpenTofu forces every state modification command to write a backup file. You'll have to remove these files manually if you don't want to keep them around. Command-Line Friendly[​](https://opentofu.org/docs/v1.11/cli/commands/state/#command-line-friendly "Direct link to Command-Line Friendly") ------------------------------------------------------------------------------------------------------------------------------------------- The output and command-line structure of the state subcommands is designed to be usable with Unix command-line tools such as grep, awk, and similar PowerShell commands. For advanced filtering and modification, we recommend piping OpenTofu state subcommands together with other command line tools. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/state/#usage) * [Remote State](https://opentofu.org/docs/v1.11/cli/commands/state/#remote-state) * [Backups](https://opentofu.org/docs/v1.11/cli/commands/state/#backups) * [Command-Line Friendly](https://opentofu.org/docs/v1.11/cli/commands/state/#command-line-friendly) --- # Ephemeral resources | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Ephemeral resources =================== Note Ephemeral resources can be used only with OpenTofu from v1.11 onwards. The `ephemeral` block defines a temporary value that OpenTofu will not store in state or plan. This block works only with providers that already offer such capability and is not meant to be used as a drop-in replacement for other blocks (`data` or `resource`). To understand if providers offer such capability, the provider documentation or schema should be consulted. Lifecycle[​](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#lifecycle "Direct link to Lifecycle") ------------------------------------------------------------------------------------------------------------------------------ The lifecycle of an ephemeral resource is different than the lifecycle of other resource types. When OpenTofu encounters such a block, it will execute the following sequence: * Validate the configuration using the specified provider. * Open the ephemeral resource to retrieve the value from the provider. * Close the ephemeral resource when it is no longer needed in the execution of the current phase Any attribute of the response returned by opening the ephemeral resource, is marked as `ephemeral` and can only be used in specific contexts: * [Ephemeral Resources](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/) * [Ephemeral Variables](https://opentofu.org/docs/v1.11/language/values/variables/#ephemerality) * [Ephemeral Outputs](https://opentofu.org/docs/v1.11/language/values/outputs/#ephemerality) * [Locals](https://opentofu.org/docs/v1.11/language/values/locals/#ephemerality) * [Providers](https://opentofu.org/docs/v1.11/language/providers/configuration/) * [Provisioners](https://opentofu.org/docs/v1.11/language/resources/provisioners/syntax/#suppressing-provisioner-logs-in-cli-output) * [Resource `connection` blocks](https://opentofu.org/docs/v1.11/language/resources/provisioners/connection/#ephemeral-usage) * [Resource `write-only` attributes](https://opentofu.org/docs/v1.11/language/ephemerality/write-only-attributes/) Any usage of an `ephemeral` value in contexts where is not allowed will generate an error. Configuration structure[​](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#configuration-structure "Direct link to Configuration structure") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Besides the attributes in the schema of an ephemeral resource, the block supports also the following meta-arguments: * [`depends_on`](https://opentofu.org/docs/v1.11/language/meta-arguments/depends_on/) * [`count`](https://opentofu.org/docs/v1.11/language/meta-arguments/count/) * [`for_each`](https://opentofu.org/docs/v1.11/language/meta-arguments/for_each/) * [`provider`](https://opentofu.org/docs/v1.11/language/meta-arguments/resource-provider/) * [`lifecycle`](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#lifecycle-customizations) Lifecycle Customizations[​](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#lifecycle-customizations "Direct link to Lifecycle Customizations") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A `lifecycle` block inside an `ephemeral` block allows some customization of OpenTofu's behavior relating to instances of a resource at different phases of its lifecycle. Code Block ephemeral "example" "example" { # ...normal resource arguments... lifecycle { # ...lifecycle arguments... }} The following arguments and nested block types are supported in the `lifecycle` block for an ephemeral resource: * `enabled` (bool) - Controls whether the ephemeral resource will be used by OpenTofu. When set to `false`, the resource is excluded from the configuration as if it didn't exist. When set to `true` (the default), the resource operates normally. For ephemeral resources in particular, you can use the boolean `terraform.applying` value with `enabled` to specify that a particular ephemeral resource should be active only during the apply phase, which can be useful for values used only by managed resource provisioners because provisioners are active only during the apply phase. For more information, refer to [the `enabled` meta-argument](https://opentofu.org/docs/v1.11/language/meta-arguments/enabled/) . * `precondition` and `postcondition` blocks, as described in [Custom Conditions](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/#preconditions-and-postconditions) . Deferred opening[​](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#deferred-opening "Direct link to Deferred opening") --------------------------------------------------------------------------------------------------------------------------------------------------- By design, the ephemeral resources cannot be opened if the configuration is not fully known. When that happens during planning, the ephemeral resource will be postponed (deferred) for the apply phase. On the apply phase, based on the dependency graph, the ephemeral resource will be opened only after all of its dependencies will be satisfied. Example[​](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#example "Direct link to Example") ------------------------------------------------------------------------------------------------------------------------ For an in-depth example on how to use ephemeral resources, please refer to [this example](https://opentofu.org/docs/v1.11/language/ephemerality/#usage-example) . * [Lifecycle](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#lifecycle) * [Configuration structure](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#configuration-structure) * [Lifecycle Customizations](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#lifecycle-customizations) * [Deferred opening](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#deferred-opening) * [Example](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#example) --- # Command: apply | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/apply/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: apply ============== The `tofu apply` command executes the actions proposed in a OpenTofu plan. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/apply/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------- Usage: `tofu apply [options] [plan file]` ### Automatic Plan Mode[​](https://opentofu.org/docs/v1.11/cli/commands/apply/#automatic-plan-mode "Direct link to Automatic Plan Mode") When you run `tofu apply` without passing a saved plan file, OpenTofu automatically creates a new execution plan as if you had run [`tofu plan`](https://opentofu.org/docs/v1.11/cli/commands/plan/) , prompts you to approve that plan, and takes the indicated actions. You can use all of the [planning modes](https://opentofu.org/docs/v1.11/cli/commands/plan/#planning-modes) and [planning options](https://opentofu.org/docs/v1.11/cli/commands/plan/#planning-options) to customize how OpenTofu will create the plan. You can pass the `-auto-approve` option to instruct OpenTofu to apply the plan without asking for confirmation. Warning If you use `-auto-approve`, we recommend making sure that no one can change your infrastructure outside of your OpenTofu workflow. This minimizes the risk of unpredictable changes and configuration drift. ### Saved Plan Mode[​](https://opentofu.org/docs/v1.11/cli/commands/apply/#saved-plan-mode "Direct link to Saved Plan Mode") When you pass a [saved plan file](https://opentofu.org/docs/v1.11/cli/commands/plan/#out-filename) to `tofu apply`, OpenTofu takes the actions in the saved plan without prompting you for confirmation. You may want to use this two-step workflow when running OpenTofu in automation. Use [`tofu show`](https://opentofu.org/docs/v1.11/cli/commands/show/) to inspect a saved plan file before applying it. When using a saved plan, you cannot specify any additional planning modes or options. These options only affect OpenTofu's decisions about which actions to take, and the plan file contains the final results of those decisions. #### Ephemeral variables[​](https://opentofu.org/docs/v1.11/cli/commands/apply/#ephemeral-variables "Direct link to Ephemeral variables") Since ephemeral variables can't be stored in a planfile, any ephemeral variables set during the generation of a planfile from `tofu plan` must also be set when running tofu apply. For example, if `-var` has been used to provide an ephemeral variable `token` to create the planfile (`tofu plan -var "token=$MY_TOKEN"`), the same argument _must_ be set for the apply command (`tofu apply -var "token=$MY_TOKEN" planfile`). If required ephemeral variables are not provided to the apply command, OpenTofu will exit with a clear message of additional variables that must be specified. ### Plan Options[​](https://opentofu.org/docs/v1.11/cli/commands/apply/#plan-options "Direct link to Plan Options") Without a saved plan file, `tofu apply` supports all planning modes and planning options available for `tofu plan`. * **[Planning Modes](https://opentofu.org/docs/v1.11/cli/commands/plan/#planning-modes) :** These include `-destroy`, which creates a plan to destroy all remote objects, and `-refresh-only`, which creates a plan to update OpenTofu state and root module output values. * **[Planning Options](https://opentofu.org/docs/v1.11/cli/commands/plan/#planning-options) :** These include specifying which resource instances OpenTofu should replace, setting OpenTofu input variables, etc. ### Apply Options[​](https://opentofu.org/docs/v1.11/cli/commands/apply/#apply-options "Direct link to Apply Options") The following options change how the apply command executes and reports on the apply operation. * `-auto-approve` - Skips interactive approval of plan before applying. This option is ignored when you pass a previously-saved plan file, because OpenTofu considers you passing the plan file as the approval and so will never prompt in that case. * `-compact-warnings` - Shows any warning messages in a compact form which includes only the summary messages, unless the warnings are accompanied by at least one error and thus the warning text might be useful context for the errors. * `-consolidate-warnings=false` - If OpenTofu produces any warnings, no consolidation will be performed. All locations, for all warnings will be listed. Enabled by default. * `-consolidate-errors` - If OpenTofu produces any errors, attempt to consolidate similar messages into a single item. * `-input=false` - Disables all of OpenTofu's interactive prompts. Note that this also prevents OpenTofu from prompting for interactive approval of a plan, so OpenTofu will conservatively assume that you do not wish to apply the plan, causing the operation to fail. * `-json` - Enables the [machine readable JSON UI](https://opentofu.org/docs/v1.11/internals/machine-readable-ui/) output. This implies `-input=false`, so the configuration must have no unassigned variable values to continue. To enable this flag, you must also either enable the `-auto-approve` flag or specify a previously-saved plan. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * `-no-color` - Disables terminal formatting sequences in the output. Use this if you are running OpenTofu in a context where its output will be rendered by a system that cannot interpret terminal formatting. * `-concise` - Disables progress-related messages in the output. * `-parallelism=n` - Limit the number of concurrent operation as OpenTofu [walks the graph](https://opentofu.org/docs/v1.11/internals/graph/#walking-the-graph) . Defaults to 10. * `-var 'foo=bar'` - Set a variable in the OpenTofu configuration. This flag can be set multiple times. * `-var-file=foo` - Set variables in the OpenTofu configuration from a file. If "terraform.tfvars" or any ".auto.tfvars" files are present, they will be automatically loaded. * `-show-sensitive` - If specified, sensitive values will not be redacted in te UI output. * `-deprecation` - Specify what type of warnings are shown. Accepted values: "module:all", "module:local", "module:none". Default: module:all. When "module:all" is selected, OpenTofu will show the deprecation warnings for all modules. When "module:local" is selected, the warnings will be shown only for the modules that are imported with a relative path. When "module:none" is selected, all the deprecation warnings will be dropped. * All [planning modes](https://opentofu.org/docs/v1.11/cli/commands/plan/#planning-modes) and [planning options](https://opentofu.org/docs/v1.11/cli/commands/plan/#planning-options) for `tofu plan` - Customize how OpenTofu will create the plan. Only available when you run `tofu apply` without a saved plan file. For configurations using [the `local` backend](https://opentofu.org/docs/v1.11/language/settings/backends/local/) only, `tofu apply` also accepts the legacy options [`-state`, `-state-out`, and `-backup`](https://opentofu.org/docs/v1.11/language/settings/backends/local/#command-line-arguments) . ### Environment variables[​](https://opentofu.org/docs/v1.11/cli/commands/apply/#environment-variables "Direct link to Environment variables") You can further customize behavior of `apply` command by using [environment variables](https://opentofu.org/docs/v1.11/cli/config/environment-variables/) . For example, the [TF\_STATE\_PERSIST\_INTERVAL](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_state_persist_interval) environment variable allows to specify the interval between state persistence. Passing a Different Configuration Directory[​](https://opentofu.org/docs/v1.11/cli/commands/apply/#passing-a-different-configuration-directory "Direct link to Passing a Different Configuration Directory") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If your workflow relies on overriding the root module directory, use [the `-chdir` global option](https://opentofu.org/docs/v1.11/#switching-working-directory-with-chdir) instead, which works across all commands and makes OpenTofu consistently look in the given directory for all files it would normally read or write in the current working directory. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/apply/#usage) * [Automatic Plan Mode](https://opentofu.org/docs/v1.11/cli/commands/apply/#automatic-plan-mode) * [Saved Plan Mode](https://opentofu.org/docs/v1.11/cli/commands/apply/#saved-plan-mode) * [Plan Options](https://opentofu.org/docs/v1.11/cli/commands/apply/#plan-options) * [Apply Options](https://opentofu.org/docs/v1.11/cli/commands/apply/#apply-options) * [Environment variables](https://opentofu.org/docs/v1.11/cli/commands/apply/#environment-variables) * [Passing a Different Configuration Directory](https://opentofu.org/docs/v1.11/cli/commands/apply/#passing-a-different-configuration-directory) --- # CLI Configuration File | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/config/config-file/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page CLI Configuration File (`.tofurc` or `tofu.rc`) =============================================== The CLI configuration file configures per-user settings for CLI behaviors, which apply across all OpenTofu working directories. This is separate from [your infrastructure configuration](https://opentofu.org/docs/v1.11/language/) . Locations[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#locations "Direct link to Locations") ----------------------------------------------------------------------------------------------------------- The configuration can be placed in a single file whose location depends on the host operating system: * On Windows, the file must be named `tofu.rc` and placed in the relevant user's `%APPDATA%` directory. The physical location of this directory depends on your Windows version and system configuration; use `$env:APPDATA` in PowerShell to find its location on your system. The `terraform.rc` is supported for backward-compatibility purposes. If both `terraform.rc` and `tofu.rc` files exists, the later would take precedence. * On all other systems, the file must be named `.tofurc` (note the leading period) and placed directly in the home directory of the relevant user or be named `tofurc` and placed in a valid [XDG Base Directory](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) config directory such as `$XDG_CONFIG_HOME/opentofu`. The `.terraformrc` is supported for backward-compatibility purposes. If both `.terraformrc` and `.tofurc` files exists, the latter would take precedence. When using an XDG config directory `.terraformrc` and `terraformrc` are ignored. On Windows, beware of Windows Explorer's default behavior of hiding filename extensions. OpenTofu will not recognize a file named `tofuc.rc.txt` as a CLI configuration file, even though Windows Explorer may _display_ its name as just `tofu.rc`. Use `dir` from PowerShell or Command Prompt to confirm the filename. The location of the OpenTofu CLI configuration file can also be specified using the `TF_CLI_CONFIG_FILE` [environment variable](https://opentofu.org/docs/v1.11/cli/config/environment-variables/) . Any such file should follow the naming pattern `*.tfrc`. Configuration File Syntax[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#configuration-file-syntax "Direct link to Configuration File Syntax") ----------------------------------------------------------------------------------------------------------------------------------------------------------- The configuration file uses the same _HCL_ syntax as `.tf` and `.tofu` files, but with different attributes and blocks. The following example illustrates the general syntax; see the following section for information on the meaning of each of these settings: Code Block plugin_cache_dir = "$HOME/.terraform.d/plugin-cache" Available Settings[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#available-settings "Direct link to Available Settings") -------------------------------------------------------------------------------------------------------------------------------------- The following settings can be set in the CLI configuration file: * `credentials` - configures credentials for use with a cloud backend. See [Credentials](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials) below for more information. * `credentials_helper` - configures an external helper program for the storage and retrieval of credentials for cloud backends. See [Credentials Helpers](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials-helpers) below for more information. * `oci_credentials` and `default_oci_credentials` - configures credentials for interacting with an OCI Registry. Refer to [OCI Registry Credentials](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/) for more information. * `plugin_cache_dir` β€” enables [plugin caching](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-plugin-cache) and specifies, as a string, the location of the plugin cache directory. * `provider_installation` - customizes the installation methods used by `tofu init` when installing provider plugins. See [Provider Installation](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation) below for more information. * `registry_protocols` - configures some infrequently-needed settings controlling how OpenTofu requests metadata from module and provider registries. Refer to [Registry Protocol Settings](https://opentofu.org/docs/v1.11/cli/config/config-file/#registry-protocol-settings) below for more information. Credentials[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials "Direct link to Credentials") ----------------------------------------------------------------------------------------------------------------- When interacting with OpenTofu-specific network services, OpenTofu expects to find API tokens in CLI configuration files in `credentials` blocks: Code Block credentials "app.opentofu.org" { token = "xxxxxx.atlasv1.zzzzzzzzzzzzz"} If you are running the OpenTofu CLI interactively on a computer with a web browser, you can use [the `tofu login` command](https://opentofu.org/docs/v1.11/cli/commands/login/) to get credentials and automatically save them in the CLI configuration. If not, you can manually write `credentials` blocks. You can have multiple `credentials` blocks if you regularly use services from multiple hosts. Each `credentials` block contains a `token` argument giving the API token to use for that host. Note The credentials hostname must match the hostname in your module sources and/or backend configuration. `credentials` blocks are used only for OpenTofu-specific protocols. You can configure credentials for OCI Registries using `oci_credentials` blocks, as described in [OCI Registry Credentials](https://opentofu.org/docs/v1.11/cli/oci_registries/credentials/) . ### Environment Variable Credentials[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#environment-variable-credentials "Direct link to Environment Variable Credentials") If you would prefer not to store your API tokens directly in the CLI configuration, you may use a host-specific environment variable. Environment variable names should have the prefix `TF_TOKEN_` added to the domain name, with periods encoded as underscores. For example, the value of a variable named `TF_TOKEN_app_opentofu_org` will be used as a bearer authorization token when the CLI makes service requests to the hostname `app.opentofu.org`. You must convert domain names containing non-ASCII characters to their [punycode equivalent](https://www.charset.org/punycode) with an ACE prefix. For example, token credentials for δΎ‹γˆγ°.com must be set in a variable called `TF_TOKEN_xn--r8j3dr99h_com`. Hyphens are also valid within host names but usually invalid as variable names and may be encoded as double underscores. For example, you can set a token for the domain name `cafΓ©.fr` as `TF_TOKEN_xn--caf-dma.fr`, `TF_TOKEN_xn--caf-dma_fr`, or `TF_TOKEN_xn____caf__dma_fr`. If multiple variables evaluate to the same hostname, OpenTofu will choose the one defined last in the operating system's variable table. ### Credentials Helpers[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials-helpers "Direct link to Credentials Helpers") You can configure a `credentials_helper` to instruct OpenTofu to use a different credentials storage mechanism. Code Block credentials_helper "example" { args = []} `credentials_helper` is a configuration block that can appear at most once in the CLI configuration. Its label (`"example"` above) is the name of the credentials helper to use. The `args` argument is optional and allows passing additional arguments to the helper program, for example if it needs to be configured with the address of a remote host to access for credentials. A configured credentials helper will be consulted only to retrieve credentials for hosts that are _not_ explicitly configured in a `credentials` block as described in the previous section. Conversely, this means you can override the credentials returned by the helper for a specific hostname by writing a `credentials` block alongside the `credentials_helper` block. OpenTofu does not include any credentials helpers in the main distribution. To learn how to write and install your own credentials helpers to integrate with existing in-house credentials management systems, see [the guide to Credentials Helper internals](https://opentofu.org/docs/v1.11/internals/credentials-helpers/) . ### Credentials Source Priority Order[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials-source-priority-order "Direct link to Credentials Source Priority Order") Credentials found in an environment variable for a particular service host as described above will be preferred over those in CLI config as set by `tofu login`. If neither are set, any configured credentials helper will be consulted. Provider Installation[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation "Direct link to Provider Installation") ----------------------------------------------------------------------------------------------------------------------------------------------- The default way to install provider plugins is from a provider registry. The origin registry for a provider is encoded in the provider's source address, like `registry.opentofu.org/hashicorp/aws`. For convenience in the common case, OpenTofu allows omitting the hostname portion for providers on `registry.opentofu.org`, so you can write shorter public provider addresses like `hashicorp/aws`. Downloading a plugin directly from its origin registry is not always appropriate, though. For example, the system where you are running OpenTofu may not be able to access an origin registry due to firewall restrictions within your organization or your locality. To allow using OpenTofu providers in these situations, there are some alternative options for making provider plugins available to OpenTofu which we'll describe in the following sections. ### Explicit Installation Method Configuration[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#explicit-installation-method-configuration "Direct link to Explicit Installation Method Configuration") A `provider_installation` block in the CLI configuration allows overriding OpenTofu's default installation behaviors, so you can force OpenTofu to use a local mirror for some or all of the providers you intend to use. The general structure of a `provider_installation` block is as follows: Code Block provider_installation { filesystem_mirror { path = "/usr/share/terraform/providers" include = ["example.com/*/*"] } direct { exclude = ["example.com/*/*"] }} Each of the nested blocks inside the `provider_installation` block specifies one installation method. Each installation method can take both `include` and `exclude` patterns that specify which providers a particular installation method can be used for. In the example above, we specify that any provider whose origin registry is at `example.com` can be installed only from the filesystem mirror at `/usr/share/terraform/providers`, while all other providers can be installed only directly from their origin registries. If you set both `include` and `exclude` for a particular installation method, the exclusion patterns take priority. For example, including `registry.opentofu.org/hashicorp/*` but also excluding `registry.opentofu.org/hashicorp/dns` will make that installation method apply to everything in the `hashicorp` namespace with the exception of `hashicorp/dns`. As with provider source addresses in the main configuration, you can omit the `registry.opentofu.org/` prefix for providers distributed through the public OpenTofu Registry, even when using wildcards. For example, `registry.opentofu.org/hashicorp/*` and `hashicorp/*` are equivalent. `*/*` is a shorthand for `registry.opentofu.org/*/*`, not for `*/*/*`. The following are the supported installation method types: * `direct`: request information about the provider directly from its origin registry and download over the network from the location that registry indicates. This method expects no additional arguments. * `filesystem_mirror`: consult a directory on the local disk for copies of providers. This method requires the additional argument `path` to indicate which directory to look in. OpenTofu expects the given directory to contain a nested directory structure where the path segments together provide metadata about the available providers. The following two directory structures are supported: * Packed layout: `HOSTNAME/NAMESPACE/TYPE/terraform-provider-TYPE_VERSION_TARGET.zip` is the distribution zip file obtained from the provider's origin registry. * Unpacked layout: `HOSTNAME/NAMESPACE/TYPE/VERSION/TARGET` is a directory containing the result of extracting the provider's distribution zip file. In both layouts, the `VERSION` is a string like `2.0.0` and the `TARGET` specifies a particular target platform using a format like `darwin_amd64`, `linux_arm`, `windows_amd64`, etc. If you use the unpacked layout, OpenTofu will attempt to create a symbolic link to the mirror directory when installing the provider, rather than creating a deep copy of the directory. The packed layout prevents this because OpenTofu must extract the zip file during installation. You can include multiple `filesystem_mirror` blocks in order to specify several different directories to search. * `network_mirror`: consult a particular HTTPS server for copies of providers, regardless of which registry host they belong to. This method requires the additional argument `url` to indicate the mirror base URL, which should use the `https:` scheme and end with a trailing slash. OpenTofu expects the given URL to be a base URL for an implementation of [the provider network mirror protocol](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/) , which is designed to be relatively easy to implement using typical static website hosting mechanisms. * `oci_mirror`: map provider source addresses into OCI repository addresses, regardless of which registry host they belong to, and then retrieve them using the OCI Distribution protocol. This is similar to `network_mirror`, but uses the industry-standard OCI registry protocol instead of the OpenTofu-specific provider network mirror protocol to allow you to reuse a pre-existing OCI registry service. For more information, refer to [Provider Mirrors in OCI Registries](https://opentofu.org/docs/v1.11/cli/oci_registries/provider-mirror/) . Warning Don't configure `network_mirror` URLs that you do not trust. Provider mirror servers are subject to TLS certificate checks to verify identity, but a network mirror with a TLS certificate can potentially serve modified copies of upstream providers with malicious content. The `direct` and `network_mirror` methods support an additional argument `download_retry_count`. When specified, it will be used to retry downloading the provider binary in case of retryable errors (connection reset and a range of 500 errors). Code Block provider_installation { network_mirror { url = "https://example.com/" include = ["example.com/*/*"] download_retry_count = 2 } direct { exclude = ["example.com/*/*"] download_retry_count = 3 }} You can use this argument to disable fully the retries in case of a specific method (`download_retry_count = 0`). Note When used together with [`TF_PROVIDER_DOWNLOAD_RETRY`](https://opentofu.org/docs/v1.11/cli/config/environment-variables/#tf_provider_download_retry) , the configuration value will be used for each method that it is configured with. For the methods with no such configuration, the environment variable will be used instead. OpenTofu will try all of the specified methods whose include and exclude patterns match a given provider, and select the newest version available across all of those methods that matches the version constraint given in each OpenTofu configuration. If you have a local mirror of a particular provider and intend OpenTofu to use that local mirror exclusively, you must either remove the `direct` installation method altogether or use its `exclude` argument to disable its use for specific providers. ### Implied Local Mirror Directories[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#implied-local-mirror-directories "Direct link to Implied Local Mirror Directories") If your CLI configuration does not include a `provider_installation` block at all, OpenTofu produces an _implied_ configuration. The implied configuration includes a selection of `filesystem_mirror` methods and then the `direct` method. The set of directories OpenTofu can select as filesystem mirrors depends on the operating system where you are running OpenTofu: * **Windows:** `%APPDATA%/terraform.d/plugins` and `%APPDATA%/HashiCorp/Terraform/plugins` * **Mac OS X:** `$HOME/.terraform.d/plugins`, `~/Library/Application Support/io.terraform/plugins`, and `/Library/Application Support/io.terraform/plugins` * **Linux and other Unix-like systems**:`$HOME/.terraform.d/plugins` and `opentofu/plugins` located within a valid [XDG Base Directory](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) data directory such as `$XDG_DATA_HOME/opentofu/plugins`. If a `terraform.d/plugins` directory exists in the current working directory then OpenTofu will also include that directory, regardless of your operating system. This behavior changes when you use the `-chdir` option with the `init` command. In that case, OpenTofu checks for the `terraform.d/plugins` directory in the launch directory and not in the directory you specified with `-chdir`. OpenTofu will check each of the paths above to see if it exists, and if so treat it as a filesystem mirror. The directory structure inside each one must therefore match one of the two structures described for `filesystem_mirror` blocks in [Explicit Installation Method Configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/#explicit-installation-method-configuration) . In addition to the zero or more implied `filesystem_mirror` blocks, OpenTofu also creates an implied `direct` block. OpenTofu will scan all of the filesystem mirror directories to see which providers are placed there and automatically exclude all of those providers from the implied `direct` block. (This automatic `exclude` behavior applies only to _implicit_ `direct` blocks; if you use explicit `provider_installation` you will need to write the intended exclusions out yourself.) ### Provider Plugin Cache[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-plugin-cache "Direct link to Provider Plugin Cache") By default, `tofu init` downloads plugins into a subdirectory of the working directory so that each working directory is self-contained. As a consequence, if you have multiple configurations that use the same provider then a separate copy of its plugin will be downloaded for each configuration. Given that provider plugins can be quite large (on the order of hundreds of megabytes), this default behavior can be inconvenient for those with slow or metered Internet connections. Therefore OpenTofu optionally allows the use of a local directory as a shared plugin cache, which then allows each distinct plugin binary to be downloaded only once. To enable the plugin cache, use the `plugin_cache_dir` setting in the CLI configuration file. For example: Code Block plugin_cache_dir = "$HOME/.terraform.d/plugin-cache" This directory must already exist before OpenTofu will cache plugins; OpenTofu will not create the directory itself. Please note that on Windows it is necessary to use forward slash separators (`/`) rather than the conventional backslash (`\`) since the configuration file parser considers a backslash to begin an escape sequence. Setting this in the configuration file is the recommended approach for a persistent setting. Alternatively, the `TF_PLUGIN_CACHE_DIR` environment variable can be used to enable caching or to override an existing cache directory within a particular shell session: Code Block export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache" When a plugin cache directory is enabled, the `tofu init` command will still use the configured or implied installation methods to obtain metadata about which plugins are available, but once a suitable version has been selected it will first check to see if the chosen plugin is already available in the cache directory. If so, OpenTofu will use the previously-downloaded copy. If the selected plugin is not already in the cache, OpenTofu will download it into the cache first and then copy it from there into the correct location under your current working directory. When possible OpenTofu will use symbolic links to avoid storing a separate copy of a cached plugin in multiple directories. The plugin cache directory _must not_ also be one of the configured or implied filesystem mirror directories, since the cache management logic conflicts with the filesystem mirror logic when operating on the same directory. OpenTofu will never itself delete a plugin from the plugin cache once it has been placed there. Over time, as plugins are upgraded, the cache directory may grow to contain several unused versions which you must delete manually. Note The plugin cache directory makes a best effort to be concurrency safe. It uses standard file locking practices (fnctl flock or LockFileEx), which have different guarantees depending on Operating System and filesystem. ### Allowing the Provider Plugin Cache to break the dependency lock file[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#allowing-the-provider-plugin-cache-to-break-the-dependency-lock-file "Direct link to Allowing the Provider Plugin Cache to break the dependency lock file") Note The option described in is for unusual and exceptional situations only. Do not set this option unless you are sure you need it and you fully understand the consequences of enabling it. By default OpenTofu will use packages from the global cache directory only if they match at least one of the checksums recorded in the [dependency lock file](https://opentofu.org/docs/v1.11/language/files/dependency-lock/) for that provider. This ensures that OpenTofu can always generate a complete and correct dependency lock file entry the first time you use a new provider in a particular configuration. However, we know that in some special situations teams have been unable to use the dependency lock file as intended, and so they don't include it in their version control as recommended and instead let OpenTofu re-generate it each time it installs providers. For those teams that don't preserve the dependency lock file in their version control systems between runs, OpenTofu allows an additional CLI Configuration setting which tells OpenTofu to always treat a package in the cache directory as valid even if there isn't already an entry in the dependency lock file to confirm it: Code Block plugin_cache_may_break_dependency_lock_file = true Alternatively, you can set the environment variable `TF_PLUGIN_CACHE_MAY_BREAK_DEPENDENCY_LOCK_FILE` to any value other than the empty string or `0`, which is equivalent to the above setting. Setting this option gives OpenTofu CLI permission to create an incomplete dependency lock file entry for a provider if that would allow OpenTofu to use the cache to install that provider. In that situation the dependency lock file will be valid for use on the current system but may not be valid for use on another computer with a different operating system or CPU architecture, because it will include only a checksum of the package in the global cache. We recommend that most users leave this option unset, in which case OpenTofu will always install a provider from upstream the first time you use it with a particular configuration, but can then re-use the cache entry on later runs once the dependency lock file records valid checksums for the provider package. Note The OpenTofu team intends to improve the dependency lock file mechanism in future versions so that it will be usable in more situations. At that time this option will become silently ignored. If your workflow relies on the use of this option, please open a GitHub issue to share details about your situation so that we can consider how to support it without breaking the dependency lock file. ### Development Overrides for Provider Developers[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#development-overrides-for-provider-developers "Direct link to Development Overrides for Provider Developers") Normally OpenTofu verifies version selections and checksums for providers in order to help ensure that all operations are made with the intended version of a provider, and that authors can gradually upgrade to newer provider versions in a controlled manner. These version and checksum rules are inconvenient when developing a provider though, because we often want to try a test configuration against a development build of a provider that doesn't even have an associated version number yet, and doesn't have an official set of checksums listed in a provider registry. As a convenience for provider development, OpenTofu supports a special additional block `dev_overrides` in `provider_installation` blocks. The contents of this block effectively override all of the other configured installation methods, so a block of this type must always appear first in the sequence: Code Block provider_installation { # Use /home/developer/tmp/terraform-null as an overridden package directory # for the hashicorp/null provider. This disables the version and checksum # verifications for this provider and forces OpenTofu to look for the # null provider plugin in the given directory. dev_overrides { "hashicorp/null" = "/home/developer/tmp/terraform-null" } # For all other providers, install them directly from their origin provider # registries as normal. If you omit this, OpenTofu will _only_ use # the dev_overrides block, and so no other providers will be available. direct {}} With development overrides in effect, the `tofu init` command will still attempt to select a suitable published version of your provider to install and record in [the dependency lock file](https://opentofu.org/docs/v1.11/language/files/dependency-lock/) for future use, but other commands like `tofu apply` will disregard the lock file's entry for `hashicorp/null` and will use the given directory instead. Once your new changes are included in a published release of the provider, you can use `tofu init -upgrade` to select the new version in the dependency lock file and remove your development override. The override path for a particular provider should be a directory similar to what would be included in a `.zip` file when distributing the provider. At minimum that includes an executable file named with a prefix like `terraform-provider-null`, where `null` is the provider type. If your provider makes use of other files in its distribution package then you can copy those files into the override directory too. You may wish to enable a development override only for shell sessions where you are actively working on provider development. If so, you can write a local CLI configuration file with content like the above in your development directory, perhaps called `dev.tfrc` for the sake of example, and then use the `TF_CLI_CONFIG_FILE` environment variable to instruct OpenTofu to use that localized CLI configuration instead of the default one: Code Block export TF_CLI_CONFIG_FILE=/home/developer/tmp/dev.tfrc Development overrides are not intended for general use as a way to have OpenTofu look for providers on the local filesystem. If you wish to put copies of _released_ providers in your local filesystem, see [Implied Local Mirror Directories](https://opentofu.org/docs/v1.11/cli/config/config-file/#implied-local-mirror-directories) or [Explicit Installation Method Configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/#explicit-installation-method-configuration) instead. This development overrides mechanism is intended as a pragmatic way to enable smoother provider development. The details of how it behaves, how to configure it, and how it interacts with the dependency lock file may all evolve in future OpenTofu releases, including possible breaking changes. We therefore recommend using development overrides only temporarily during provider development work. Registry Protocol Settings[​](https://opentofu.org/docs/v1.11/cli/config/config-file/#registry-protocol-settings "Direct link to Registry Protocol Settings") -------------------------------------------------------------------------------------------------------------------------------------------------------------- The CLI configuration block `registry_protocols` controls a small number of rarely-needed settings for customizing the retry behavior and request timeouts when OpenTofu makes metadata requests to module and provider registries. Code Block registry_protocols { # retry_count specifies how many times OpenTofu can # retry a registry metadata request when the response # is a retry-eligible error. # # This can also be set using an environment variable: # TF_REGISTRY_DISCOVERY_RETRY=1 retry_count = 1 # request_timeout_seconds specifies how long OpenTofu # should wait for a response to a registry metadata # request, in seconds. # # This can also be set using an environment variable: # TF_REGISTRY_CLIENT_TIMEOUT=10 request_timeout_seconds = 10} The values in the example above are the current defaults, although the defaults are subject to change in future versions of OpenTofu. These settings are used only when making requests to the _OpenTofu-native_ registry protocols, and when performing service discovery to find service endpoints for a particular hostname. These settings do not affect any other requests made by OpenTofu, including requests to download the actual module or provider packages, or requests to other kinds of installation sources such as OCI registries. * [Locations](https://opentofu.org/docs/v1.11/cli/config/config-file/#locations) * [Configuration File Syntax](https://opentofu.org/docs/v1.11/cli/config/config-file/#configuration-file-syntax) * [Available Settings](https://opentofu.org/docs/v1.11/cli/config/config-file/#available-settings) * [Credentials](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials) * [Environment Variable Credentials](https://opentofu.org/docs/v1.11/cli/config/config-file/#environment-variable-credentials) * [Credentials Helpers](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials-helpers) * [Credentials Source Priority Order](https://opentofu.org/docs/v1.11/cli/config/config-file/#credentials-source-priority-order) * [Provider Installation](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation) * [Explicit Installation Method Configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/#explicit-installation-method-configuration) * [Implied Local Mirror Directories](https://opentofu.org/docs/v1.11/cli/config/config-file/#implied-local-mirror-directories) * [Provider Plugin Cache](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-plugin-cache) * [Allowing the Provider Plugin Cache to break the dependency lock file](https://opentofu.org/docs/v1.11/cli/config/config-file/#allowing-the-provider-plugin-cache-to-break-the-dependency-lock-file) * [Development Overrides for Provider Developers](https://opentofu.org/docs/v1.11/cli/config/config-file/#development-overrides-for-provider-developers) * [Registry Protocol Settings](https://opentofu.org/docs/v1.11/cli/config/config-file/#registry-protocol-settings) --- # Command: refresh | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/refresh/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: refresh ================ The `tofu refresh` command reads the current settings from all managed remote objects and updates the OpenTofu state to match. Warning This command is deprecated, because its default behavior is unsafe if you have misconfigured credentials for any of your providers. See below for more information and recommended alternatives. This won't modify your real remote objects, but it will modify the [OpenTofu state](https://opentofu.org/docs/v1.11/language/state/) . You shouldn't typically need to use this command, because OpenTofu automatically performs the same refreshing actions as a part of creating a plan in both the [`tofu plan`](https://opentofu.org/docs/v1.11/cli/commands/plan/) and [`tofu apply`](https://opentofu.org/docs/v1.11/cli/commands/apply/) commands. This command is here primarily for backward compatibility, but we don't recommend using it because it provides no opportunity to review the effects of the operation before updating the state. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/refresh/#usage "Direct link to Usage") --------------------------------------------------------------------------------------------- Usage: `tofu refresh [options]` This command is effectively an alias for the following command: Code Block tofu apply -refresh-only -auto-approve Consequently, it supports all of the same options as [`tofu apply`](https://opentofu.org/docs/v1.11/cli/commands/apply/) except that it does not accept a saved plan file, it doesn't allow selecting a planning mode other than "refresh only", and `-auto-approve` is always enabled. Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu refresh`. Automatically applying the effect of a refresh is risky. If you have misconfigured credentials for one or more providers, OpenTofu may be misled into thinking that all of the managed objects have been deleted, causing it to remove all of the tracked objects without any confirmation prompt. Instead, we recommend using the following command in order to get the same effect but with the opportunity to review the changes that OpenTofu has detected before committing them to the state: Code Block tofu apply -refresh-only This alternative command will present an interactive prompt for you to confirm the detected changes. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/refresh/#usage) --- # Command: show | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/show/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: show ============= The `tofu show` command can inspect various OpenTofu artifacts and produce either human-readable or machine-readable descriptions. For example, you can use `tofu show` to inspect a saved plan file to check that the planned operations are acceptable, or to inspect the latest state snapshot. Note When using the `-json` command-line flag, any sensitive values in OpenTofu state will be returned in plain text. For more information, see [Sensitive Data in State](https://opentofu.org/docs/v1.11/language/state/sensitive-data/) . Usage[​](https://opentofu.org/docs/v1.11/cli/commands/show/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------ Usage: `tofu show [target-selection-option] [other-options]` Use one of the following target selection options to specify the artifact to inspect: * `-state`: Inspect the latest state snapshot, if any. * `-plan=FILENAME`: Inspect the plan stored in the given saved plan file. * `-config`: Inspect the current full configuration (requires `-json`). * `-module=DIR`: Inspect the configuration of just a single module in the given directory, without requiring any dependencies to be installed (requires `-json`). The `-state` option is the default if none of these options are used. The target-selection options are mutually-exclusive. This command also accepts the following additional options: * `-no-color`: Disables the use of terminal escape sequences in human-oriented output. * `-json`: Selects the machine-readable JSON output format, instead of the default human-oriented output. * `-var` and `-var-file`: Specifies values for any input variables used in module source addresses or backend settings in the current configuration. * `-show-sensitive`: If specified, sensitive values will be displayed. Unless using the `-module=DIR` option, this command relies on schema information from provider plugins to fully understand the provider-specific data structures in state, plan, and configuration artifacts. If you are currently using different provider versions than were used when creating the selected artifact then you may need to use `tofu apply` (or similar) to allow OpenTofu to upgrade the stored data to match the latest provider schemas. JSON Output[​](https://opentofu.org/docs/v1.11/cli/commands/show/#json-output "Direct link to JSON Output") ------------------------------------------------------------------------------------------------------------ When using the `-json` option, the structure of the machine-readable output depends on the selected artifact type: * `-state` returns [the JSON state representation](https://opentofu.org/docs/v1.11/internals/json-format/#state-representation) . * `-plan=FILENAME` returns the [the JSON plan representation](https://opentofu.org/docs/v1.11/internals/json-format/#plan-representation) , which also includes information about the configuration and prior state that the plan was based on. * `-config` returns [the JSON configuration representation](https://opentofu.org/docs/v1.11/internals/json-format/#configuration-representation) , providing exactly the same configuration-related information that the plan representation would include, but without requiring a plan to be created first. * `-module=DIR` returns a subset of [the JSON configuration representation](https://opentofu.org/docs/v1.11/internals/json-format/#configuration-representation) , where: * The `"module"` property of each module call is omitted. * The `"schema_version"` property of each resource is omitted. * All expression-related properties are omitted. These omissions together allow this particular mode to work without first executing `tofu init`, and thus without first installing the module's dependencies. Legacy Usage[​](https://opentofu.org/docs/v1.11/cli/commands/show/#legacy-usage "Direct link to Legacy Usage") --------------------------------------------------------------------------------------------------------------- For backward compatibility with older versions of OpenTofu, this command also supports a different usage pattern: `tofu show [other-options] ` In this style, none of the explicit target selection options can be used and instead OpenTofu inspects the given file and reacts in the following ways: * If the file can be loaded as a saved plan file, behaves like `-plan=FILENAME` with the same file. * If the file can be parsed as a local state snapshot file such as those created by `tofu state pull`, inspects the content of that state file using the same output format as would normally be used to inspect the latest state snapshot. The selected state snapshot file must be one associated with the configuration in the current working directory, or else the results are unspecified because the available providers might not match those that were used to create the data in the state snapshot. Unless you need the legacy behavior of inspecting an arbitrary state snapshot file, we recommend using the new explicit target selection options to make it clearer to OpenTofu what artifact type you wish to inspect. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/show/#usage) * [JSON Output](https://opentofu.org/docs/v1.11/cli/commands/show/#json-output) * [Legacy Usage](https://opentofu.org/docs/v1.11/cli/commands/show/#legacy-usage) --- # Command: version | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/version/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: version ================ The `tofu version` displays the current version of OpenTofu and all installed plugins. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/version/#usage "Direct link to Usage") --------------------------------------------------------------------------------------------- Usage: `tofu version [options]` With no additional arguments, `version` will display the version of OpenTofu, the platform it's installed on, and installed providers. This command has one optional flag: * `-json` - If specified, the version information is formatted as a JSON object, and no upgrade or security information is included. Example[​](https://opentofu.org/docs/v1.11/cli/commands/version/#example "Direct link to Example") --------------------------------------------------------------------------------------------------- Basic usage, with security information shown if relevant: Code Block $ tofu versionOpenTofu v1.6.0on darwin_amd64+ provider registry.opentofu.org/hashicorp/null v3.0.0 As JSON: Code Block $ tofu version -json{ "terraform_version": "0.16.0-alpha2", "platform": "darwin_amd64", "provider_selections": { "registry.opentofu.org/hashicorp/null": "3.0.0" }} * [Usage](https://opentofu.org/docs/v1.11/cli/commands/version/#usage) * [Example](https://opentofu.org/docs/v1.11/cli/commands/version/#example) --- # Command: workspace show | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/workspace/show/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: workspace show ======================= The `tofu workspace show` command is used to output the current workspace. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/workspace/show/#usage "Direct link to Usage") ---------------------------------------------------------------------------------------------------- Usage: `tofu workspace show` The command will display the current workspace. Example[​](https://opentofu.org/docs/v1.11/cli/commands/workspace/show/#example "Direct link to Example") ---------------------------------------------------------------------------------------------------------- Code Block $ tofu workspace showdevelopment * [Usage](https://opentofu.org/docs/v1.11/cli/commands/workspace/show/#usage) * [Example](https://opentofu.org/docs/v1.11/cli/commands/workspace/show/#example) --- # Command: providers | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/providers/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: providers ================== The `tofu providers` command shows information about the [provider requirements](https://opentofu.org/docs/v1.11/language/providers/requirements/) of the configuration in the current working directory, as an aid to understanding where each requirement was detected from. This command also has several subcommands with different purposes. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/providers/#usage "Direct link to Usage") ----------------------------------------------------------------------------------------------- Usage: `tofu providers [options]` Code Block $ tofu providersProviders required by configuration:.└── module.submodule β”œβ”€β”€ provider[registry.opentofu.org/hashicorp/tfcoremock] └── module.nestedProviders required by state: provider[registry.opentofu.org/hashicorp/tfcoremock] Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu providers`. This command accepts the following options: * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/providers/#usage) --- # Expressions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/expressions/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) Expressions =========== _Expressions_ refer to or compute values within a configuration. The simplest expressions are just literal values, like `"hello"` or `5`, but the OpenTofu language also allows more complex expressions such as references to data exported by resources, arithmetic, conditional evaluation, and a number of built-in functions. Expressions can be used in a number of places in the OpenTofu language, but some contexts limit which expression constructs are allowed, such as requiring a literal value of a particular type or forbidding [references to resource attributes](https://opentofu.org/docs/v1.11/language/expressions/references/#references-to-resource-attributes) . Each language feature's documentation describes any restrictions it places on expressions. You can experiment with the behavior of OpenTofu's expressions from the OpenTofu expression console, by running [the `tofu console` command](https://opentofu.org/docs/v1.11/cli/commands/console/) . The other pages in this section describe the features of OpenTofu's expression syntax. * [Types and Values](https://opentofu.org/docs/v1.11/language/expressions/types/) documents the data types that OpenTofu expressions can resolve to, and the literal syntaxes for values of those types. * [Strings and Templates](https://opentofu.org/docs/v1.11/language/expressions/strings/) documents the syntaxes for string literals, including interpolation sequences and template directives. * [References to Values](https://opentofu.org/docs/v1.11/language/expressions/references/) documents how to refer to named values like variables and resource attributes. * [Operators](https://opentofu.org/docs/v1.11/language/expressions/operators/) documents the arithmetic, comparison, and logical operators. * [Function Calls](https://opentofu.org/docs/v1.11/language/expressions/function-calls/) documents the syntax for calling OpenTofu's built-in functions. * [Conditional Expressions](https://opentofu.org/docs/v1.11/language/expressions/conditionals/) documents the ` ? : ` expression, which chooses between two values based on a bool condition. * [For Expressions](https://opentofu.org/docs/v1.11/language/expressions/for/) documents expressions like `[for s in var.list : upper(s)]`, which can transform a complex type value into another complex type value. * [Splat Expressions](https://opentofu.org/docs/v1.11/language/expressions/splat/) documents expressions like `var.list[*].id`, which can extract simpler collections from more complicated expressions. * [Dynamic Blocks](https://opentofu.org/docs/v1.11/language/expressions/dynamic-blocks/) documents a way to create multiple repeatable nested blocks within a resource or other construct. * [Type Constraints](https://opentofu.org/docs/v1.11/language/expressions/type-constraints/) documents the syntax for referring to a type, rather than a value of that type. Input variables expect this syntax in their `type` argument. * [Version Constraints](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/) documents the syntax of special strings that define a set of allowed software versions. OpenTofu uses version constraints in several places. --- # Command: untaint | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/untaint/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: untaint ================ OpenTofu has a marker called "tainted" which it uses to track that an object might be damaged and so a future OpenTofu plan ought to replace it. OpenTofu automatically marks an object as "tainted" if an error occurs during a multi-step "create" action, because OpenTofu can't be sure that the object was left in a fully-functional state. You can also manually mark an object as "tainted" using the deprecated command [`tofu taint`](https://opentofu.org/docs/v1.11/cli/commands/taint/) , although we no longer recommend that workflow. If OpenTofu currently considers a particular object as tainted but you've determined that it's actually functioning correctly and need _not_ be replaced, you can use `tofu untaint` to remove the taint marker from that object. This command _will not_ modify any real remote objects, but will modify the state in order to remove the tainted status. If you remove the taint marker from an object but then later discover that it was degraded after all, you can create and apply a plan to replace it without first re-tainting the object, by using a command like the following: Code Block tofu apply -replace="aws_instance.example[0]" Usage[​](https://opentofu.org/docs/v1.11/cli/commands/untaint/#usage "Direct link to Usage") --------------------------------------------------------------------------------------------- Usage: `tofu untaint [options] address` The `address` argument is a [resource address](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/) identifying a particular resource instance which is currently tainted. Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu untaint`. This command also accepts the following options: * `-allow-missing` - If specified, the command will succeed (exit code 0) even if the resource is missing. The command might still return an error for other situations, such as if there is a problem reading or writing the state. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * `-no-color` - Disables terminal formatting sequences in the output. Use this if you are running OpenTofu in a context where its output will be rendered by a system that cannot interpret terminal formatting. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.11/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.11/language/settings/backends/remote/) only, `tofu untaint` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/v1.11/cli/cloud/command-line-arguments/#ignore-remote-version) . For configurations using [the `local` backend](https://opentofu.org/docs/v1.11/language/settings/backends/local/) only, `tofu untaint` also accepts the legacy options [`-state`, `-state-out`, and `-backup`](https://opentofu.org/docs/v1.11/language/settings/backends/local/#command-line-arguments) . * [Usage](https://opentofu.org/docs/v1.11/cli/commands/untaint/#usage) --- # Command: taint | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/taint/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: taint ============== The `tofu taint` command informs OpenTofu that a particular object has become degraded or damaged. OpenTofu represents this by marking the object as "tainted" in the OpenTofu state, and OpenTofu will propose to replace it in the next plan you create. Warning This command is deprecated, we recommend using the `-replace` option with `tofu apply` instead (details below). Recommended Alternative[​](https://opentofu.org/docs/v1.11/cli/commands/taint/#recommended-alternative "Direct link to Recommended Alternative") ------------------------------------------------------------------------------------------------------------------------------------------------- We recommend using the [`-replace` option](https://opentofu.org/docs/v1.11/cli/commands/plan/#replace-address) with `tofu apply` to force OpenTofu to replace an object even though there are no configuration changes that would require it. Code Block $ tofu apply -replace="aws_instance.example[0]" We recommend the `-replace` option because the change will be reflected in the OpenTofu plan, letting you understand how it will affect your infrastructure before you take any externally-visible action. When you use `tofu taint`, other users could create a new plan against your tainted object before you can review the effects. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/taint/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------- Code Block $ tofu taint [options]
The `address` argument is the address of the resource to mark as tainted. The address is in [the resource address syntax](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/) , as shown in the output from other commands, such as: * `aws_instance.foo` * `aws_instance.bar[1]` * `aws_instance.baz[\"key\"]` (quotes in resource addresses must be escaped on the command line, so that they will not be interpreted by your shell) * `module.foo.module.bar.aws_instance.qux` Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu taint`. This command accepts the following options: * `-allow-missing` - If specified, the command will succeed (exit code 0) even if the resource is missing. The command might still return an error for other situations, such as if there is a problem reading or writing the state. * `-lock=false` - Disables OpenTofu's default behavior of attempting to take a read/write lock on the state for the duration of the operation. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.11/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.11/language/settings/backends/remote/) only, `tofu taint` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/v1.11/cli/cloud/command-line-arguments/#ignore-remote-version) . For configurations using [the `local` backend](https://opentofu.org/docs/v1.11/language/settings/backends/local/) only, `tofu taint` also accepts the legacy options [`-state`, `-state-out`, and `-backup`](https://opentofu.org/docs/v1.11/language/settings/backends/local/#command-line-arguments) . * [Recommended Alternative](https://opentofu.org/docs/v1.11/cli/commands/taint/#recommended-alternative) * [Usage](https://opentofu.org/docs/v1.11/cli/commands/taint/#usage) --- # Command: providers mirror | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/providers/mirror/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: providers mirror ========================= The `tofu providers mirror` command downloads the providers required for the current configuration and copies them into a directory in the local filesystem. In normal use, `tofu init` will automatically download needed providers from provider registries as part of initializing the current working directory. Sometimes OpenTofu is running in an environment where that isn't possible, such as on an isolated network without access to an OpenTofu Registry. In that case, [explicit installation method configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/#explicit-installation-method-configuration) allows you to configure OpenTofu, when running on a particular system, to consult only a local filesystem directory where you've created a local mirror of the necessary plugins, and to skip accessing the upstream registry at all. The `tofu providers mirror` command can automatically populate a directory that will be used as a local filesystem mirror in the provider installation configuration. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/providers/mirror/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------------ Usage: `tofu providers mirror [options] ` A single target directory is required. OpenTofu will create under that directory the path structure that is expected for filesystem-based provider plugin mirrors, populating it with `.zip` files containing the plugins themselves. Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu providers mirror`. This command accepts the following generic options: * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. OpenTofu will also generate various `.json` index files which contain suitable responses to implement [the network mirror protocol](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/) , if you upload the resulting directory to a static website host. OpenTofu ignores those index files when using the directory as a filesystem mirror, because the directory entries themselves are authoritative in that case. This command supports the following additional options: * `-platform=OS_ARCH` - Choose which target platform to build a mirror for. By default OpenTofu will obtain plugin packages suitable for the platform where you run this command. Use this flag multiple times to include packages for multiple target systems. Target platform names consist of an operating system and a CPU architecture. For example, `linux_amd64` selects the Linux operating system running on an AMD64 or x86\_64 CPU. You can run `tofu providers mirror` again on an existing mirror directory to update it with new packages. For example, you can add packages for a new target platform by re-running the command with the desired new `-platform=...` option, and it will place the packages for that new platform without removing packages you previously downloaded, merging the resulting set of packages together to update the JSON index files. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/providers/mirror/#usage) --- # Command: state push | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/state/push/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state push =================== The `tofu state push` command is used to manually upload a local state file to [remote state](https://opentofu.org/docs/v1.11/language/state/remote/) . This command also works with local state. This command should rarely be used. It is meant only as a utility in case manual intervention is necessary with the remote state. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/state/push/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------ Usage: `tofu state push [options] PATH` This command pushes the state specified by PATH to the currently configured [backend](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/) . If PATH is "-" then the state data to push is read from stdin. This data is loaded completely into memory and verified prior to being written to the destination state. Note OpenTofu state files must be in UTF-8 format without a byte order mark (BOM). For PowerShell on Windows, use `Set-Content` to automatically encode files in UTF-8 format. For example, run `tofu state push | sc terraform.tfstate`. OpenTofu will perform a number of safety checks to prevent you from making changes that appear to be unsafe: * **Differing lineage**: If the "lineage" value in the state differs, OpenTofu will not allow you to push the state. A differing lineage suggests that the states are completely different and you may lose data. * **Higher remote serial**: If the "serial" value in the destination state is higher than the state being pushed, OpenTofu will prevent the push. A higher serial suggests that data is in the destination state that isn't accounted for in the local state being pushed. Both of these safety checks can be disabled with the `-force` flag. **This is not recommended.** If you disable the safety checks and are pushing state, the destination state will be overwritten. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.11/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.11/language/settings/backends/remote/) only, `tofu state push` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/cli/cloud/command-line-arguments/#ignore-remote-version) . Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu state push`. This command also accepts the following options for tofu state push: * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * [`ignore-remote-version`](https://opentofu.org/docs/v1.11/cli/cloud/command-line-arguments/#ignore-remote-version) . * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/state/push/#usage) --- # Command: state pull | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/state/pull/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state pull =================== The `tofu state pull` command is used to manually download and output the state from [remote state](https://opentofu.org/docs/v1.11/language/state/remote/) . This command also works with local state. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/state/pull/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------ Usage: `tofu state pull` This command downloads the state from its current location, upgrades the local copy to the latest state file version that is compatible with locally-installed OpenTofu, and outputs the raw format to stdout. This is useful for reading values out of state (potentially pairing this command with something like [jq](https://stedolan.github.io/jq/) ). It is also useful if you need to make manual modifications to state. You cannot use this command to inspect the OpenTofu version of the remote state, as it will always be converted to the current OpenTofu version before output. Note OpenTofu state files must be in UTF-8 format without a byte order mark (BOM). For PowerShell on Windows, use `Set-Content` to automatically encode files in UTF-8 format. For example, run `tofu state pull | sc terraform.tfstate`. Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu state pull`. The command support the following command-line arguments: * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/state/pull/#usage) --- # Command: workspace new | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/workspace/new/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: workspace new ====================== The `tofu workspace new` command is used to create a new workspace. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/workspace/new/#usage "Direct link to Usage") --------------------------------------------------------------------------------------------------- Usage: `tofu workspace new [OPTIONS] NAME [DIR]` This command will create a new workspace with the given name. A workspace with this name must not already exist. If the `-state` flag is given, the state specified by the given path will be copied to initialize the state for this new workspace. Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu workspace new`. The command-line flags are all optional. The supported flags are: * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Duration to retry a state lock. Default 0s. * `-state=path` - Path to an existing state file to initialize the state of this environment. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. Example: Create[​](https://opentofu.org/docs/v1.11/cli/commands/workspace/new/#example-create "Direct link to Example: Create") -------------------------------------------------------------------------------------------------------------------------------- Code Block $ tofu workspace new exampleCreated and switched to workspace "example"!You're now on a new, empty workspace. Workspaces isolate their state,so if you run "tofu plan" OpenTofu will not see any existing statefor this configuration. Example: Create from State[​](https://opentofu.org/docs/v1.11/cli/commands/workspace/new/#example-create-from-state "Direct link to Example: Create from State") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- To create a new workspace from a pre-existing local state file: Code Block $ tofu workspace new -state=old.terraform.tfstate exampleCreated and switched to workspace "example".You're now on a new, empty workspace. Workspaces isolate their state,so if you run "tofu plan" OpenTofu will not see any existing statefor this configuration. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/workspace/new/#usage) * [Example: Create](https://opentofu.org/docs/v1.11/cli/commands/workspace/new/#example-create) * [Example: Create from State](https://opentofu.org/docs/v1.11/cli/commands/workspace/new/#example-create-from-state) --- # Command: workspace list | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/workspace/list/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: workspace list ======================= The `tofu workspace list` command is used to list all existing workspaces. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/workspace/list/#usage "Direct link to Usage") ---------------------------------------------------------------------------------------------------- Usage: `tofu workspace list [DIR]` The command will list all existing workspaces. The current workspace is indicated using an asterisk (`*`) marker. Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu workspace list`. This command also accepts the following options: * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. Example[​](https://opentofu.org/docs/v1.11/cli/commands/workspace/list/#example "Direct link to Example") ---------------------------------------------------------------------------------------------------------- Code Block $ tofu workspace list default* development jsmith-test * [Usage](https://opentofu.org/docs/v1.11/cli/commands/workspace/list/#usage) * [Example](https://opentofu.org/docs/v1.11/cli/commands/workspace/list/#example) --- # Command: workspace delete | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/workspace/delete/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: workspace delete ========================= The `tofu workspace delete` command is used to delete an existing workspace. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/workspace/delete/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------------ Usage: `tofu workspace delete [OPTIONS] NAME [DIR]` This command will delete the specified workspace. To delete a workspace, it must already exist, it must not be tracking resources, and it must not be your current workspace. If the workspace is tracking resources, OpenTofu will not allow you to delete it unless the `-force` flag is specified. Additionally, different [backends](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#backend-types) may implement other restrictions on whether a workspace is considered safe to delete without the `-force` flag, such as whether the workspace is locked. If you delete a workspace which is tracking resources (via `-force`), then resources may become "dangling". These are resources that physically exist but that OpenTofu can no longer manage. This is sometimes preferred: you may want OpenTofu to stop managing resources, so they can be managed some other way. Most of the time, however, this is not intended and so OpenTofu protects you from getting into this situation. Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu workspace delete`. The command-line flags are all optional. The only supported flags are: * `-force` - Delete the workspace even if it is tracking resources. After deletion, OpenTofu can no longer track or manage the workspace's infrastructure. Defaults to false. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Duration to retry a state lock. Default 0s. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. Example[​](https://opentofu.org/docs/v1.11/cli/commands/workspace/delete/#example "Direct link to Example") ------------------------------------------------------------------------------------------------------------ Code Block $ tofu workspace delete exampleDeleted workspace "example". * [Usage](https://opentofu.org/docs/v1.11/cli/commands/workspace/delete/#usage) * [Example](https://opentofu.org/docs/v1.11/cli/commands/workspace/delete/#example) --- # OpenTofu CLI Documentation | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.6/cli/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) This is documentation for OpenTofu **1.6.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://opentofu.org/docs/v1.11/) ** (1.11.x). OpenTofu CLI Documentation ========================== This is the documentation for OpenTofu CLI. It is relevant to anyone working with OpenTofu's CLI-based workflows; this includes people who use OpenTofu CLI by itself, as well as those who use OpenTofu CLI in conjunction with TACOS (TF Automation and Collaboration Software). Notably, this documentation does not cover the syntax and usage of the OpenTofu language. For that, see the [OpenTofu Language Documentation](https://opentofu.org/docs/v1.6/language/) . --- # Command: workspace select | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/workspace/select/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: workspace select ========================= The `tofu workspace select` command is used to choose a different workspace to use for further operations. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/workspace/select/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------------ Usage: `tofu workspace select NAME [DIR]` This command will select another workspace. The named workspace must already exist. Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu workspace select`. The supported flags are: * `-or-create` - If the workspace that is being selected does not exist, create it. Default is `false`. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. Example[​](https://opentofu.org/docs/v1.11/cli/commands/workspace/select/#example "Direct link to Example") ------------------------------------------------------------------------------------------------------------ Code Block $ tofu workspace list default* development jsmith-test$ tofu workspace select defaultSwitched to workspace "default". * [Usage](https://opentofu.org/docs/v1.11/cli/commands/workspace/select/#usage) * [Example](https://opentofu.org/docs/v1.11/cli/commands/workspace/select/#example) --- # Ephemerality | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/ephemerality/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Ephemerality ============ Ephemerality refers to the nature of a value to be "ephemeral", meaning that it will not be stored in the state or the plan. With this concept, transient and/or confidental information can be safely handled within OpenTofu. Related concepts: * [Sensitive](https://opentofu.org/docs/v1.11/language/state/sensitive-data/) resource fields, outputs and variables * Marking values as sensitive ensures the contents are sanitized from the user interface. * Sensitive values will still be stored in plaintext in the state and plan. * [State Encryption](https://opentofu.org/docs/v1.11/language/state/encryption/) * Encryption of state and plan data can be configured to prevent unauthorized access and tampering. * Security of this data is determined by the encryption methods used and access to the encryption keys. In contrast, Ephemeral values only exist for the duration of single execution of the `tofu` command and are never stored in state or plan data. This enables representation of transient concepts, such as temporary network tunnels or confidential keys managed by an external system. It is recommended that all three concepts are considered when working with confidential information. If possible use ephemeral values/resources to prevent storing the data at all. If confidential data must be stored, ensure that it is marked as sensitive and that state and plan encryption are enabled and properly configured. As part of this concept, the following constructs can be used: * [Ephemeral Resources](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/) * [Ephemeral Variables](https://opentofu.org/docs/v1.11/language/values/variables/#ephemerality) * [Ephemeral Outputs](https://opentofu.org/docs/v1.11/language/values/outputs/#ephemerality) * [Locals](https://opentofu.org/docs/v1.11/language/values/locals/#ephemerality) * [Providers](https://opentofu.org/docs/v1.11/language/providers/configuration/) * [Provisioners](https://opentofu.org/docs/v1.11/language/resources/provisioners/syntax/#suppressing-provisioner-logs-in-cli-output) * [Resource `connection` blocks](https://opentofu.org/docs/v1.11/language/resources/provisioners/connection/#ephemeral-usage) * [Resource `write-only` attributes](https://opentofu.org/docs/v1.11/language/ephemerality/write-only-attributes/) Compatibility[​](https://opentofu.org/docs/v1.11/language/ephemerality/#compatibility "Direct link to Compatibility") ---------------------------------------------------------------------------------------------------------------------- Warning This concept is inspired by and aims for compatibility with the equivalent "Ephemeral" concept in Terraform v1.12. If incompatibilities are discovered, the OpenTofu team will consider accepting breaking changes in subsequent versions of OpenTofu to ensure compatibility. Additional Topics[​](https://opentofu.org/docs/v1.11/language/ephemerality/#additional-topics "Direct link to Additional Topics") ---------------------------------------------------------------------------------------------------------------------------------- * [Providing values for root module ephemeral variables](https://opentofu.org/docs/v1.11/cli/commands/apply/#ephemeral-variables) * [Validations interaction with ephemeral values](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/#ephemeral-values-usage) * [Sanitizing values using `ephemeralasnull()`](https://opentofu.org/docs/v1.11/language/functions/ephemeralasnull/) * [Differentiating plan/apply with `tofu.applying`](https://opentofu.org/docs/v1.11/language/expressions/references/#filesystem-and-workspace-info) * [How configuration generation handles write-only attributes](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#generated-hints) Usage example[​](https://opentofu.org/docs/v1.11/language/ephemerality/#usage-example "Direct link to Usage example") ---------------------------------------------------------------------------------------------------------------------- Note The following example is meant to showcase how ephemeral concepts listed above work together and is not intended to be used directly in real environments ### A module to handle various usage patterns of secrets[​](https://opentofu.org/docs/v1.11/language/ephemerality/#a-module-to-handle-various-usage-patterns-of-secrets "Direct link to A module to handle various usage patterns of secrets") In the following example you can see a module that can handle secret creation and retrieval by using ephemeral variables, ephemeral resources, write-only attributes, ephemeral outputs and validations using ephemeral values in their `condition`. Code Block terraform { required_providers { aws = { source = "hashicorp/aws" version = ">=6.0.0" } }}variable "secret_map" { type = map(string) default = null # default because in some cases this module can be used only for reading the secret and not storing it ephemeral = true # defines an ephemeral variable since it holds the secrets to be processed description = "The map of secrets to be used to create the new secret entry. Omit this when using this module to read the secret"}variable "secret_version" { # needed to update a write-only attribute type = number default = 0 description = "The version used to update the secret. You need to bump this from the previous version in order for the secret_map content to be persisted. Omit this when using this module to read the secret"}variable "secret_manager_arn" { type = string default = "" description = "The map of secrets to be used to create the new secret entry" validation { condition = (var.secret_manager_arn == "" && var.secret_map != null) || (var.secret_manager_arn != "" && var.secret_map == null) error_message = "var.secret_manager_arn should not be used in the same time with var.secret_map. Use the module only with var.secret_manager_arn to read the secret or use it with var.secret_map and var.secret_version to create a new secret" }}resource "aws_secretsmanager_secret" "manager" { count = var.secret_version > 0 ? 1 : 0 # used when we create a new secret manager name = "testin-secret-manager"}resource "aws_secretsmanager_secret_version" "secret_creation" { count = var.secret_version > 0 ? 1 : 0 # used when we want to create a new secret secret_id = aws_secretsmanager_secret.manager[0].arn secret_string_wo = jsonencode(var.secret_map) # here we pass in the ephemeral variable into a write-only attribute secret_string_wo_version = var.secret_version # and when we want to update it, we can provide a different value for var.secret_map and an incremented secret_version}ephemeral "aws_secretsmanager_secret_version" "secret_retrieval" { # used to read the secret from the secret manager after creating it count = var.secret_version > 0 ? 1 : 0 secret_id = aws_secretsmanager_secret.manager[0].arn depends_on = [ aws_secretsmanager_secret_version.secret_creation # ensure that we want for the secret creation before reading it ]}ephemeral "aws_secretsmanager_secret_version" "secret_retrieval_direct" { # used to read the secret from the secret manager when the module is used only for reading without creating a new secret count = var.secret_version > 0 ? 0 : 1 secret_id = var.secret_manager_arn}output "secrets" { value = "${var.secret_version > 0 ? jsondecode(ephemeral.aws_secretsmanager_secret_version.secret_retrieval[0].secret_string) : jsondecode(ephemeral.aws_secretsmanager_secret_version.secret_retrieval_direct[0].secret_string)}" ephemeral = true # marking an output as ephemeral is mandatory when the value points to an ephemeral value}output "secret_manager_arn" { value = var.secret_version > 0 ? aws_secretsmanager_secret.manager[0].arn : null # available only when the module is used to create a secret} ### Using the module in a configuration to store a secret[​](https://opentofu.org/docs/v1.11/language/ephemerality/#using-the-module-in-a-configuration-to-store-a-secret "Direct link to Using the module in a configuration to store a secret") The following configuration uses the module above to create a new secret where it stores the given aws credentials and outputs the ARN of the created secret manager: Code Block terraform { required_providers { aws = { source = "hashicorp/aws" version = "6.0.0-beta1" } }}provider "aws" { alias = "secrets-read-write"}variable "access_key" { type = string ephemeral = true}variable "secret_key" { type = string ephemeral = true}locals { secrets = { "access_key" : var.access_key, "secret_key" : var.secret_key }}module "secret_management" { providers = { aws = aws.secrets-read-write } source = "../mod" secret_map = local.secrets secret_version = 1 # first version of the secret. If want to update the secret inside, bump this version}output "secret_manager_arn" { value = module.secret_management.secret_manager_arn} ### Using the module in a configuration to retrieve a secret and configure a provider[​](https://opentofu.org/docs/v1.11/language/ephemerality/#using-the-module-in-a-configuration-to-retrieve-a-secret-and-configure-a-provider "Direct link to Using the module in a configuration to retrieve a secret and configure a provider") The following configuration uses the module above to read the secret, configure a provider with the credentials retrieved and store the same credentials in a write-only attribute `value_wo` of the `aws_ssm_parameter` resource. Additionally, it adds two `local-exec` provisioners. The execution of the first one will print the `command` content but the second one will print `(output suppressed due to ephemeral value in config)`: Code Block terraform { required_providers { aws = { source = "hashicorp/aws" version = "6.0.0-beta1" } }}provider "aws" { alias = "read-secrets"}variable "secret_manager_arn" { type = string}module "secret_management" { providers = { aws = aws.read-secrets } source = "../mod" secret_manager_arn = var.secret_manager_arn}# Provider can be configured with the credentials returned by the ephemeral resource inside the module.provider "aws" { alias = "dev-access" access_key = module.secret_management.secrets["access_key"] secret_key = module.secret_management.secrets["secret_key"]}resource "aws_ssm_parameter" "store_ephemeral_in_write_only" { provider = aws.dev-access name = "parameter_from_ephemeral_value" type = "SecureString" value_wo = jsonencode(module.secret_management.secrets) # Using the secrets again in a write-only attribute value_wo_version = 1 # bump this if `value_wo` needs to be updated # Because this provisioner uses only regular attributes, it will print the output of the command provisioner "local-exec" { when = create command = "echo non-ephemeral value: ${aws_ssm_parameter.store_ephemeral_in_write_only.arn}" } # Because this provisioner uses ephemeral values, its output will be suppressed provisioner "local-exec" { when = create command = "echo ephemeral value from module: #${jsonencode(module.secret_management.secrets)}#" }} * [Compatibility](https://opentofu.org/docs/v1.11/language/ephemerality/#compatibility) * [Additional Topics](https://opentofu.org/docs/v1.11/language/ephemerality/#additional-topics) * [Usage example](https://opentofu.org/docs/v1.11/language/ephemerality/#usage-example) * [A module to handle various usage patterns of secrets](https://opentofu.org/docs/v1.11/language/ephemerality/#a-module-to-handle-various-usage-patterns-of-secrets) * [Using the module in a configuration to store a secret](https://opentofu.org/docs/v1.11/language/ephemerality/#using-the-module-in-a-configuration-to-store-a-secret) * [Using the module in a configuration to retrieve a secret and configure a provider](https://opentofu.org/docs/v1.11/language/ephemerality/#using-the-module-in-a-configuration-to-retrieve-a-secret-and-configure-a-provider) --- # Dependency Lock File | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Dependency Lock File ==================== An OpenTofu configuration may refer to two different kinds of external dependency that come from outside of its own codebase: * [Providers](https://opentofu.org/docs/v1.11/language/providers/requirements/) , which are plugins for OpenTofu that extend it with support for interacting with various external systems. * [Modules](https://opentofu.org/docs/v1.11/language/modules/) , which allow splitting out groups of OpenTofu configuration constructs (written in the OpenTofu language) into reusable abstractions. Both of these dependency types can be published and updated independently from OpenTofu itself and from the configurations that depend on them. For that reason, OpenTofu must determine which versions of those dependencies are potentially compatible with the current configuration and which versions are currently selected for use. [Version constraints](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/) within the configuration itself determine which versions of dependencies are _potentially_ compatible, but after selecting a specific version of each dependency OpenTofu remembers the decisions it made in a _dependency lock file_ so that it can (by default) make the same decisions again in future. At present, the dependency lock file tracks only _provider_ dependencies. OpenTofu does not remember version selections for remote modules, and so OpenTofu will always select the newest available module version that meets the specified version constraints. You can use an _exact_ version constraint to ensure that OpenTofu will always select the same module version. Lock File Location[​](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#lock-file-location "Direct link to Lock File Location") ---------------------------------------------------------------------------------------------------------------------------------------------- The dependency lock file is a file that belongs to the configuration as a whole, rather than to each separate module in the configuration. For that reason OpenTofu creates it and expects to find it in your current working directory when you run OpenTofu, which is also the directory containing the `.tf` or `.tofu` files for the root module of your configuration. The lock file is always named `.terraform.lock.hcl`, and this name is intended to signify that it is a lock file for various items that OpenTofu caches in the `.terraform` subdirectory of your working directory. OpenTofu automatically creates or updates the dependency lock file each time you run [the `tofu init` command](https://opentofu.org/docs/v1.11/cli/commands/init/) . You should include this file in your version control repository so that you can discuss potential changes to your external dependencies via code review, just as you would discuss potential changes to your configuration itself. The dependency lock file uses the same low-level syntax as the main OpenTofu language, but the dependency lock file is not itself an OpenTofu language configuration file. It is named with the suffix `.hcl` instead of `.tf` or `.tofu` in order to signify that difference. Dependency Installation Behavior[​](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#dependency-installation-behavior "Direct link to Dependency Installation Behavior") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When `tofu init` is working on installing all of the providers needed for a configuration, OpenTofu considers both the version constraints in the configuration _and_ the version selections recorded in the lock file. If a particular provider has no existing recorded selection, OpenTofu will select the newest available version that matches the given version constraint, and then update the lock file to include that selection. If a particular provider already has a selection recorded in the lock file, OpenTofu will always re-select that version for installation, even if a newer version has become available. You can override that behavior by adding the `-upgrade` option when you run `tofu init`, in which case OpenTofu will disregard the existing selections and once again select the newest available version matching the version constraint. If a particular `tofu init` call makes changes to the lock file, OpenTofu will mention that as part of its output: Code Block OpenTofu has made some changes to the provider dependency selections recordedin the .terraform.lock.hcl file. Review those changes and commit them to yourversion control system if they represent changes you intended to make. When you see this message, you can use your version control system to [review the changes OpenTofu has proposed in the file](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#understanding-lock-file-changes) , and if they represent changes you made intentionally you can send the change through your team's usual code review process. ### Checksum verification[​](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#checksum-verification "Direct link to Checksum verification") OpenTofu will also verify that each package it installs matches at least one of the checksums it previously recorded in the lock file, if any, returning an error if none of the checksums match: Code Block Error: Failed to install providerError while installing hashicorp/azurerm v2.1.0: the current package forregistry.opentofu.org/hashicorp/azurerm 2.1.0 doesn't match any of thechecksums previously recorded in the dependency lock file. This checksum verification is intended to represent a _[trust on first use](https://en.wikipedia.org/wiki/Trust_on_first_use) _ approach. When you add a new provider for the first time you can verify it in whatever way you choose or any way you are required to by relevant regulations, and then trust that OpenTofu will raise an error if a future run of `tofu init` encounters a non-matching package for the same provider version. There are two special considerations with the "trust on first use" model: * If you install a provider from an origin registry which provides checksums that are signed with a cryptographic signature, OpenTofu will treat all of the signed checksums as valid as long as one checksum matches. The lock file will therefore include checksums for both the package you installed for your current platform _and_ any other packages that might be available for other platforms. In this case, the `tofu init` output will include the fingerprint of the key that signed the checksums, with a message like `(signed, key ID 0C0AF313E5FD9F80)`. You may wish to confirm that you trust the holder of the given key before committing the lock file containing the signed checksums, or to retrieve and verify the full set of available packages for the given provider version. * If you install a provider for the first time using an alternative installation method, such as a filesystem or network mirror, OpenTofu will not be able to verify the checksums for any platform other than the one where you ran `tofu init`, and so it will not record the checksums for other platforms and so the configuration will not be usable on any other platform. To avoid this problem you can pre-populate checksums for a variety of different platforms in your lock file using [the `tofu providers lock` command](https://opentofu.org/docs/v1.11/cli/commands/providers/lock/) , which will then allow future calls to `tofu init` to verify that the packages available in your chosen mirror match the official packages from the provider's origin registry. Understanding Lock File Changes[​](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#understanding-lock-file-changes "Direct link to Understanding Lock File Changes") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Because the dependency lock file is primarily maintained automatically by OpenTofu itself, rather than being updated manually by you or your team, your version control system may show you that the file has changed. There are a few different types of changes that OpenTofu can potentially make to your lock file, which you may need to understand in order to review the proposed changes. The following sections will describe these common situations. ### Dependency on a new provider[​](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#dependency-on-a-new-provider "Direct link to Dependency on a new provider") If you add a new entry to the [provider requirements](https://opentofu.org/docs/v1.11/language/providers/requirements/) for any module in your configuration, or if you add an external module that includes a new provider dependency itself, `tofu init` will respond to that by selecting the newest version of that provider which meets all of the version constraints in the configuration, and it will record its decision as a new `provider` block in the dependency lock file. Code Block --- .terraform.lock.hcl 2020-10-07 16:12:07.539570634 -0700+++ .terraform.lock.hcl 2020-10-07 16:12:15.267487237 -0700@@ -6,6 +6,26 @@ ] }+provider "registry.opentofu.org/hashicorp/azurerm" {+ version = "2.30.0"+ constraints = "~> 2.12"+ hashes = [+ "h1:FJwsuowaG5CIdZ0WQyFZH9r6kIJeRKts9+GcRsTz1+Y=",+ "h1:c/ntSXrDYM1mUir2KufijYebPcwKqS9CRGd3duDSGfY=",+ "h1:yre4Ph76g9H84MbuhZ2z5MuldjSA4FsrX6538O7PCcY=",+ "zh:04f0a50bb2ba92f3bea6f0a9e549ace5a4c13ef0cbb6975494cac0ef7d4acb43",+ "zh:2082e12548ebcdd6fd73580e83f626ed4ed13f8cdfd51205d8696ffe54f30734",+ "zh:246bcc449e9a92679fb30f3c0a77f05513886565e2dcc66b16c4486f51533064",+ "zh:24de3930625ac9014594d79bfa42d600eca65e9022b9668b54bfd0d924e21d14",+ "zh:2a22893a576ff6f268d9bf81cf4a56406f7ba79f77826f6df51ee787f6d2840a",+ "zh:2b27485e19c2aaa9f15f29c4cff46154a9720647610171e30fc6c18ddc42ec28",+ "zh:435f24ce1fb2b63f7f02aa3c84ac29c5757cd29ec4d297ed0618423387fe7bd4",+ "zh:7d99725923de5240ff8b34b5510569aa4ebdc0bdb27b7bac2aa911a8037a3893",+ "zh:7e3b5d0af3b7411dd9dc65ec9ab6caee8c191aee0fa7f20fc4f51716e67f50c0",+ "zh:da0af4552bef5a29b88f6a0718253f3bf71ce471c959816eb7602b0dadb469ca",+ ]+}+ provider "registry.opentofu.org/newrelic/newrelic" { version = "2.1.2" constraints = "~> 2.1.1" The new lock file entry records several pieces of information: * `version`: the exact version that OpenTofu selected based on the version constraints in the configuration. * `constraints`: all of the version constraints that OpenTofu considered when making this selection. (OpenTofu doesn't actually use this information to make installation decisions, but includes it to help explain to human readers how the previous decision was made.) * `hashes`: a number of checksums that are all considered to be valid for packages implementing the selected version of this provider on different platforms. The meaning of these hashes is explained more under _[New provider package checksums](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#new-provider-package-checksums) _ below. ### New version of an existing provider[​](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#new-version-of-an-existing-provider "Direct link to New version of an existing provider") If you run `tofu init -upgrade` to ask OpenTofu to consider newer provider versions that still match the configured version constraints, OpenTofu may then select a newer version for a provider and update its existing `provider` block to reflect that change. Code Block --- .terraform.lock.hcl 2020-10-07 16:44:25.819579509 -0700+++ .terraform.lock.hcl 2020-10-07 16:43:42.785665945 -0700@@ -7,22 +7,22 @@ } provider "registry.opentofu.org/hashicorp/azurerm" {- version = "2.1.0"- constraints = "~> 2.1.0"+ version = "2.0.0"+ constraints = "2.0.0" hashes = [- "h1:EOJImaEaVThWasdqnJjfYc6/P8N/MRAq1J7avx5ZbV4=",- "zh:0015b491cf9151235e57e35ea6b89381098e61bd923f56dffc86026d58748880",- "zh:4c5682ba1e0fc7e2e602d3f103af1638f868c31fe80cc1a884a97f6dad6e1c11",- "zh:57bac885b108c91ade4a41590062309c832c9ab6bf6a68046161636fcaef1499",- "zh:5810d48f574c0e363c969b3f45276369c8f0a35b34d6202fdfceb7b85b3ac597",- "zh:5c6e37a44462b8662cf9bdd29ce30523712a45c27c5d4711738705be0785db41",- "zh:64548940a3387aa3a752e709ee9eb9982fa820fe60eb60e5f212cc1d2c58549e",- "zh:7f46749163da17330bbb5293dc825333c86304baa0a7c6256650ac536b4567c8",- "zh:8f8970f2df75ac43ffdd112055ee069d8bd1030f7eb4367cc4cf494a1fa802c3",- "zh:9ad693d00dc5d7d455d06faba70e716bce727c6706f7293288e87fd7956b8fe0",- "zh:b6e3cb55e6aec62b47edd0d2bd5e14bd6a2bcfdac65930a6e9e819934734c57b",- "zh:d6a3f3b9b05c28ecf3919e9e7afa185805a6d7442fc4b3eedba749c2731d1f0e",- "zh:d81fb624a357c57c7ea457ce543d865b39b12f26c2edd58a2f7cd43326c91010",+ "h1:bigGXBoRbp7dv79bEEn+aaju8575qEXHQ57XHVPJeB8=",+ "zh:09c603c8904ca4a5bc19e82335afbc2837dcc4bee81e395f9daccef2f2cba1c8",+ "zh:194a919d4836d6c6d4ce598d0c66cce00ddc0d0b5c40d01bb32789964d818b42",+ "zh:1f269627df4e266c4e0ef9ee2486534caa3c8bea91a201feda4bca525005aa0a",+ "zh:2bae3071bd5f8e553355c4b3a547d6efe1774a828142b762e9a4e85f79be7f63",+ "zh:6c98dfa5c3468e8d02e2b3af7c4a8a14a5d469ce5a642909643b413a17ca338b",+ "zh:7af78f61666fd45fbf428161c061ea2623162d601b79dc71d6a5158756853ffa",+ "zh:883c2df86ae9ba2a5c167cf5c2c7deca0239171a224d6d335f0fd6dd9c283830",+ "zh:a2028379078577d8ff5ecfca6e8a8b25a25ffb1686de0ee52a7fe8011783488b",+ "zh:abe6ef399552fd3861a454a839cd978c1d15735658fdc00f9054435aff0f4620",+ "zh:c30b1bf14077913c3cdf34979b1434dbb1353cb5995eb3956b191c50538b64a9",+ "zh:ca64ae2ad9793e5631e3b0b9327f7cb22cb5d8e9de57be7d85821791b1d5a375",+ "zh:fffe56904a38109bb8d613b02808a177c3ddfac19f03b3aac799281fea38f475", ] } The primary effect of selecting a new provider version is to change the value of `version` in the `provider` block. If the upgrade came along with a change to the configured version constraints, OpenTofu will also record that change in the `constraints` value. Because each version has its own set of distribution packages, switching to a new version will also tend to replace all of the values in `hashes`, to reflect the checksums of the packages for the new version. ### New provider package checksums[​](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#new-provider-package-checksums "Direct link to New provider package checksums") A more subtle change you may see in a `provider` block is the addition of new checksums that were not previously recorded, even though nothing else in the `provider` block has changed: Code Block --- .terraform.lock.hcl 2020-10-07 17:24:23.397892140 -0700+++ .terraform.lock.hcl 2020-10-07 17:24:57.423130253 -0700@@ -10,6 +10,7 @@ version = "2.1.0" constraints = "~> 2.1.0" hashes = [+ "h1:1xvaS5D8B8t6J6XmXxX8spo97tAzjhacjedFX1B47Fk=", "h1:EOJImaEaVThWasdqnJjfYc6/P8N/MRAq1J7avx5ZbV4=", "zh:0015b491cf9151235e57e35ea6b89381098e61bd923f56dffc86026d58748880", "zh:4c5682ba1e0fc7e2e602d3f103af1638f868c31fe80cc1a884a97f6dad6e1c11",\ \ The addition of a new checksum into the `hashes` value represents OpenTofu gradually transitioning between different _hashing schemes_. The `h1:` and `zh:` prefixes on these values represent different hashing schemes, each of which represents calculating a checksum using a different algorithm. We may occasionally introduce new hashing schemes if we learn of limitations in the existing schemes or if a new scheme offers some considerable additional benefit.\ \ The two hashing schemes currently supported are:\ \ * `zh:`: a mnemonic for "zip hash", this is a legacy hash format which is part of the OpenTofu provider registry protocol and is therefore used for providers that you install directly from an origin registry.\ \ This hashing scheme captures a SHA256 hash of each of the official `.zip` packages indexed in the origin registry. This is an effective scheme for verifying the official release packages when installed from a registry, but it's not suitable for verifying packages that come from other [provider installation methods](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation)\ , such as filesystem mirrors using the unpacked directory layout.\ \ * `h1:`: a mnemonic for "hash scheme 1", which is the current preferred hashing scheme.\ \ Hash scheme 1 is also a SHA256 hash, but is one computed from the _contents_ of the provider distribution package, rather than of the `.zip` archive it's contained within. This scheme therefore has the advantage that it can be calculated for an official `.zip` file, an unpacked directory with the same contents, or a recompressed `.zip` file which contains the same files but potentially different metadata or compression schemes.\ \ Due to the limited scope of the `zh:` scheme, OpenTofu will opportunistically add in the corresponding `h1:` checksums as it learns of them, which is what caused the addition of a second `h1:` checksum in the example change shown above.\ \ \ OpenTofu will add a new hash to an existing provider only if the hash is calculated from a package that _also_ matches one of the existing hashes. In the above example, OpenTofu installed a `hashicorp/azurerm` package for a different platform than that which produced the original `h1:` checksum, but was able to match it against one of the `zh:` checksums recorded previously. After confirming the `zh:` checksum match, OpenTofu then recorded the corresponding `h1:` checksum in order to gradually migrate from the old scheme to the new scheme.\ \ When installing a particular provider for the first time (where there is no existing `provider` block for it), OpenTofu will pre-populate the `hashes` value with any checksums that are covered by the provider developer's cryptographic signature, which usually covers all of the available packages for that provider version across all supported platforms. However, because the provider registry protocol still uses the `zh:` scheme, the initial set will consist primarily of hashes using that scheme, which OpenTofu will then upgrade opportunistically as you install the packages on different platforms.\ \ If you wish to avoid ongoing additions of new `h1:` hashes as you work with your configuration on new target platforms, or if you are installing providers from a mirror that therefore can't provide official signed checksums, you can ask OpenTofu to pre-populate hashes for a chosen set of platforms using [the `tofu providers lock` command](https://opentofu.org/docs/v1.11/cli/commands/providers/lock/)\ :\ \ Code Block\ \ tofu providers lock \ -platform=linux_arm64 \ -platform=linux_amd64 \ -platform=darwin_amd64 \ -platform=windows_amd64\ \ The above command will download and verify the official packages for all of the required providers across all four of the given platforms, and then record both `zh:` and `h1:` checksums for each of them in the lock file, thus avoiding the case where OpenTofu will learn about a `h1:` equivalent only at a later time. See the `tofu providers lock` documentation for more information on this command.\ \ ### Providers that are no longer required[​](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#providers-that-are-no-longer-required "Direct link to Providers that are no longer required")\ \ To determine whether there still exists a dependency on a given provider, OpenTofu uses two sources of truth: the configuration itself, and the state. If you remove the last dependency on a particular provider from both your configuration and state, then `tofu init` will remove any existing lock file entry for that provider.\ \ Code Block\ \ --- .terraform.lock.hcl 2020-10-07 16:12:07.539570634 -0700+++ .terraform.lock.hcl 2020-10-07 16:12:15.267487237 -0700@@ -6,26 +6,6 @@ ] }-provider "registry.opentofu.org/hashicorp/azurerm" {- version = "2.30.0"- constraints = "~> 2.12"- hashes = [- "h1:FJwsuowaG5CIdZ0WQyFZH9r6kIJeRKts9+GcRsTz1+Y=",- "h1:c/ntSXrDYM1mUir2KufijYebPcwKqS9CRGd3duDSGfY=",- "h1:yre4Ph76g9H84MbuhZ2z5MuldjSA4FsrX6538O7PCcY=",- "zh:04f0a50bb2ba92f3bea6f0a9e549ace5a4c13ef0cbb6975494cac0ef7d4acb43",- "zh:2082e12548ebcdd6fd73580e83f626ed4ed13f8cdfd51205d8696ffe54f30734",- "zh:246bcc449e9a92679fb30f3c0a77f05513886565e2dcc66b16c4486f51533064",- "zh:24de3930625ac9014594d79bfa42d600eca65e9022b9668b54bfd0d924e21d14",- "zh:2a22893a576ff6f268d9bf81cf4a56406f7ba79f77826f6df51ee787f6d2840a",- "zh:2b27485e19c2aaa9f15f29c4cff46154a9720647610171e30fc6c18ddc42ec28",- "zh:435f24ce1fb2b63f7f02aa3c84ac29c5757cd29ec4d297ed0618423387fe7bd4",- "zh:7d99725923de5240ff8b34b5510569aa4ebdc0bdb27b7bac2aa911a8037a3893",- "zh:7e3b5d0af3b7411dd9dc65ec9ab6caee8c191aee0fa7f20fc4f51716e67f50c0",- "zh:da0af4552bef5a29b88f6a0718253f3bf71ce471c959816eb7602b0dadb469ca",- ]-}- provider "registry.opentofu.org/newrelic/newrelic" { version = "2.1.2" constraints = "~> 2.1.1" If you add a new requirement for the same provider at a later date and run `tofu init` again, OpenTofu will treat it as if it were [an entirely new provider](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#dependency-on-a-new-provider) and so will not necessarily select the same version that was previously selected and will not be able to verify that the checksums remained unchanged. * [Lock File Location](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#lock-file-location) * [Dependency Installation Behavior](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#dependency-installation-behavior) * [Checksum verification](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#checksum-verification) * [Understanding Lock File Changes](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#understanding-lock-file-changes) * [Dependency on a new provider](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#dependency-on-a-new-provider) * [New version of an existing provider](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#new-version-of-an-existing-provider) * [New provider package checksums](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#new-provider-package-checksums) * [Providers that are no longer required](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#providers-that-are-no-longer-required) --- # CLI Authentication | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.6/cli/auth/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) This is documentation for OpenTofu **1.6.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://opentofu.org/docs/v1.11/) ** (1.11.x). CLI Authentication ================== TACOS (TF Automation and Collaboration Software) are platforms that perform as part of their offering OpenTofu runs to provision infrastructure, offering a collaboration-focused environment that makes it easier for teams to use OpenTofu together. OpenTofu CLI integrates with TACOS in several ways β€”Β it can be a front-end for CLI-driven runs, and can also use some TACOS as a state backend, a private module registry, or a private provider registry. All of these integrations require you to authenticate OpenTofu CLI with your TACOS account. The best way to handle CLI authentication is with the `login` and `logout` commands, which help automate the process of getting an API token for your TACOS user account. For details, see: * [The `tofu login` command](https://opentofu.org/docs/v1.6/cli/commands/login/) * [The `tofu logout` command](https://opentofu.org/docs/v1.6/cli/commands/logout/) --- # Command: init | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/init/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: init ============= The `tofu init` command initializes a working directory containing OpenTofu configuration files. This is the first command that should be run after writing a new OpenTofu configuration or cloning an existing one from version control. It is safe to run this command multiple times. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/init/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------ Usage: `tofu init [options]` This command performs several different initialization steps in order to prepare the current working directory for use with OpenTofu. More details on these are in the sections below, but in most cases it is not necessary to worry about these individual steps. This command is always safe to run multiple times, to bring the working directory up to date with changes in the configuration. Though subsequent runs may give errors, this command will never delete your existing configuration or state. This command requires value assignment for variables used in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) and [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) blocks. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. General Options[​](https://opentofu.org/docs/v1.11/cli/commands/init/#general-options "Direct link to General Options") ------------------------------------------------------------------------------------------------------------------------ The following options apply to all of (or several of) the initialization steps: * `-input=true` Ask for input if necessary. If false, will error if input was required. * `-lock=false` Disable locking of state files during state-related operations. * `-lock-timeout=` Override the time OpenTofu will wait to acquire a state lock. The default is `0s` (zero seconds), which causes immediate failure if the lock is already held by another process. * `-no-color` Disable color codes in the command output. * `-upgrade` Opt to upgrade modules and plugins as part of their respective installation steps. See the sections below for more details. * `-json` Produce output in a machine-readable JSON format, suitable for use in text editor integrations and other automated systems. Always disables color. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. Copy a Source Module[​](https://opentofu.org/docs/v1.11/cli/commands/init/#copy-a-source-module "Direct link to Copy a Source Module") --------------------------------------------------------------------------------------------------------------------------------------- By default, `tofu init` assumes that the working directory already contains a configuration and will attempt to initialize that configuration. Optionally, init can be run against an empty directory with the `-from-module=MODULE-SOURCE` option, in which case the given module will be copied into the target directory before any other initialization steps are run. This special mode of operation supports two use-cases: * Given a version control source, it can serve as a shorthand for checking out a configuration from version control and then initializing the working directory for it. * If the source refers to an _example_ configuration, it can be copied into a local directory to be used as a basis for a new configuration. For routine use it is recommended to check out configuration from version control separately, using the version control system's own commands. This way it is possible to pass extra flags to the version control system when necessary, and to perform other preparation steps (such as configuration generation, or activating credentials) before running `tofu init`. Backend Initialization[​](https://opentofu.org/docs/v1.11/cli/commands/init/#backend-initialization "Direct link to Backend Initialization") --------------------------------------------------------------------------------------------------------------------------------------------- During init, the root configuration directory is consulted for [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/) and the chosen backend is initialized using the given configuration settings. Note Use of [variables in the backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) block requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu init`. Re-running init with an already-initialized backend will update the working directory to use the new backend settings. Either `-reconfigure` or `-migrate-state` must be supplied to update the backend configuration. The `-migrate-state` option will attempt to copy existing state to the new backend, and depending on what changed, may result in interactive prompts to confirm migration of workspace states. The `-force-copy` option suppresses these prompts and answers "yes" to the migration questions. Enabling `-force-copy` also automatically enables the `-migrate-state` option. The `-reconfigure` option disregards any existing configuration, preventing migration of any existing state. To skip backend configuration, use `-backend=false`. Note that some other init steps require an initialized backend, so it is recommended to use this flag only when the working directory was already previously initialized for a particular backend. The `-backend-config=...` option can be used for [partial backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#partial-configuration) , in situations where the backend settings are dynamic or sensitive and so cannot be statically specified in the configuration file. Child Module Installation[​](https://opentofu.org/docs/v1.11/cli/commands/init/#child-module-installation "Direct link to Child Module Installation") ------------------------------------------------------------------------------------------------------------------------------------------------------ During init, the configuration is searched for `module` blocks, and the source code for referenced [modules](https://opentofu.org/docs/v1.11/language/modules/develop/) is retrieved from the locations given in their `source` arguments. Re-running init with modules already installed will install the sources for any modules that were added to configuration since the last init, but will not change any already-installed modules. Use `-upgrade` to override this behavior, updating all modules to the latest available source code. To skip child module installation, use `-get=false`. Note that some other init steps can complete only when the module tree is complete, so it's recommended to use this flag only when the working directory was already previously initialized with its child modules. Plugin Installation[​](https://opentofu.org/docs/v1.11/cli/commands/init/#plugin-installation "Direct link to Plugin Installation") ------------------------------------------------------------------------------------------------------------------------------------ Most OpenTofu providers are published separately from OpenTofu as plugins. During init, OpenTofu searches the configuration for both direct and indirect references to providers and attempts to install the plugins for those providers. For providers that are published in either [the public OpenTofu Registry](https://registry.opentofu.org/) or in a third-party provider registry, `tofu init` will automatically find, download, and install the necessary provider plugins. If you cannot or do not wish to install providers from their origin registries, you can customize how OpenTofu installs providers using [the provider installation settings in the CLI configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation) . For more information about specifying which providers are required for each of your modules, see [Provider Requirements](https://opentofu.org/docs/v1.11/language/providers/requirements/) . After successful installation, OpenTofu writes information about the selected providers to [the dependency lock file](https://opentofu.org/docs/v1.11/language/files/dependency-lock/) . You should commit this file to your version control system to ensure that when you run `tofu init` again in future OpenTofu will select exactly the same provider versions. Use the `-upgrade` option if you want OpenTofu to ignore the dependency lock file and consider installing newer versions. You can modify `tofu init`'s plugin behavior with the following options: * `-upgrade` Upgrade all previously-selected plugins to the newest version that complies with the configuration's version constraints. This will cause OpenTofu to ignore any selections recorded in the dependency lock file, and to take the newest available version matching the configured version constraints. * `-plugin-dir=PATH` β€”Β Force plugin installation to read plugins _only_ from the specified directory, as if it had been configured as a `filesystem_mirror` in the CLI configuration. If you intend to routinely use a particular filesystem mirror then we recommend [configuring OpenTofu's installation methods globally](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation) . You can use `-plugin-dir` as a one-time override for exceptional situations, such as if you are testing a local build of a provider plugin you are currently developing. * `-lockfile=MODE` Set a dependency lockfile mode. The valid values for the lockfile mode are as follows: * `readonly`: suppress the lockfile changes, but verify checksums against the information already recorded. It conflicts with the `-upgrade` flag. If you update the lockfile with third-party dependency management tools, it would be useful to control when it changes explicitly. Running `tofu init` in automation[​](https://opentofu.org/docs/v1.11/cli/commands/init/#running-tofu-init-in-automation "Direct link to running-tofu-init-in-automation") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- For teams that use OpenTofu as a key part of a change management and deployment pipeline, it can be desirable to orchestrate OpenTofu runs in some sort of automation in order to ensure consistency between runs, and provide other interesting features such as integration with version control hooks. There are some special concerns when running `init` in such an environment, including optionally making plugins available locally to avoid repeated re-installation. Passing a Different Configuration Directory[​](https://opentofu.org/docs/v1.11/cli/commands/init/#passing-a-different-configuration-directory "Direct link to Passing a Different Configuration Directory") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ If your workflow relies on overriding the root module directory, use [the `-chdir` global option](https://opentofu.org/docs/v1.11/cli/commands/#switching-working-directory-with-chdir) instead, which works across all commands and makes OpenTofu consistently look in the given directory for all files it would normally read or write in the current working directory. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/init/#usage) * [General Options](https://opentofu.org/docs/v1.11/cli/commands/init/#general-options) * [Copy a Source Module](https://opentofu.org/docs/v1.11/cli/commands/init/#copy-a-source-module) * [Backend Initialization](https://opentofu.org/docs/v1.11/cli/commands/init/#backend-initialization) * [Child Module Installation](https://opentofu.org/docs/v1.11/cli/commands/init/#child-module-installation) * [Plugin Installation](https://opentofu.org/docs/v1.11/cli/commands/init/#plugin-installation) * [Running `tofu init` in automation](https://opentofu.org/docs/v1.11/cli/commands/init/#running-tofu-init-in-automation) * [Passing a Different Configuration Directory](https://opentofu.org/docs/v1.11/cli/commands/init/#passing-a-different-configuration-directory) --- # Command: state list | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/state/list/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state list =================== The `tofu state list` command is used to list resources within a [OpenTofu state](https://opentofu.org/docs/v1.11/language/state/) . Usage[​](https://opentofu.org/docs/v1.11/cli/commands/state/list/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------ Usage: `tofu state list [options] [address...]` The command will list all resources in the state file matching the given addresses (if any). If no addresses are given, all resources are listed. The resources listed are sorted according to module depth order followed by alphabetical. This means that resources that are in your immediate configuration are listed first, and resources that are more deeply nested within modules are listed last. For complex infrastructures, the state can contain thousands of resources. To filter these, provide one or more patterns to the command. Patterns are in [resource addressing format](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/) . Note Use of variables in [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu state list`. The command-line flags are all optional. The following flags are available: * `-state=path` - Path to the state file. Defaults to "terraform.tfstate". Ignored when [remote state](https://opentofu.org/docs/v1.11/language/state/remote/) is used. * `-id=id` - ID of resources to show. Ignored when unset. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. Example: All Resources[​](https://opentofu.org/docs/v1.11/cli/commands/state/list/#example-all-resources "Direct link to Example: All Resources") -------------------------------------------------------------------------------------------------------------------------------------------------- This example will list all resources, including modules: Code Block $ tofu state listaws_instance.fooaws_instance.bar[0]aws_instance.bar[1]module.elb.aws_elb.main Example: Filtering by Resource[​](https://opentofu.org/docs/v1.11/cli/commands/state/list/#example-filtering-by-resource "Direct link to Example: Filtering by Resource") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This example will only list resources for the given name: Code Block $ tofu state list aws_instance.baraws_instance.bar[0]aws_instance.bar[1] Example: Filtering by Module[​](https://opentofu.org/docs/v1.11/cli/commands/state/list/#example-filtering-by-module "Direct link to Example: Filtering by Module") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- This example will list resources in the given module and any submodules: Code Block $ tofu state list module.elbmodule.elb.aws_elb.mainmodule.elb.module.secgroups.aws_security_group.sg Example: Filtering by ID[​](https://opentofu.org/docs/v1.11/cli/commands/state/list/#example-filtering-by-id "Direct link to Example: Filtering by ID") -------------------------------------------------------------------------------------------------------------------------------------------------------- This example will only list the resource whose ID is specified on the command line. This is useful to find where in your configuration a specific resource is located. Code Block $ tofu state list -id=sg-1234abcdmodule.elb.aws_security_group.sg * [Usage](https://opentofu.org/docs/v1.11/cli/commands/state/list/#usage) * [Example: All Resources](https://opentofu.org/docs/v1.11/cli/commands/state/list/#example-all-resources) * [Example: Filtering by Resource](https://opentofu.org/docs/v1.11/cli/commands/state/list/#example-filtering-by-resource) * [Example: Filtering by Module](https://opentofu.org/docs/v1.11/cli/commands/state/list/#example-filtering-by-module) * [Example: Filtering by ID](https://opentofu.org/docs/v1.11/cli/commands/state/list/#example-filtering-by-id) --- # Command: console | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/console/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: console ================ The `tofu console` command provides an interactive console for evaluating [expressions](https://opentofu.org/docs/v1.11/language/expressions/) . Warning The `tofu console` command is not designed for use in scripts. You can use it, but you may find that some functions don't work as intended. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/console/#usage "Direct link to Usage") --------------------------------------------------------------------------------------------- Usage: `tofu console [options]` This command provides an interactive command-line console for evaluating and experimenting with [expressions](https://opentofu.org/docs/v1.11/language/expressions/) . You can use it to test interpolations before using them in configurations and to interact with any values currently saved in [state](https://opentofu.org/docs/v1.11/language/state/) . If the current state is empty or has not yet been created, you can use the console to experiment with the expression syntax and [built-in functions](https://opentofu.org/docs/v1.11/language/functions/) . The console holds a [lock on the state](https://opentofu.org/docs/v1.11/language/state/locking/) , and you will not be able to use the console while performing other actions that modify state. To close the console, enter the `exit` command or press Control-C or Control-D. For configurations using [the `local` backend](https://opentofu.org/docs/v1.11/language/settings/backends/local/) only, `tofu console` accepts the legacy command line option [`-state`](https://opentofu.org/docs/v1.11/language/settings/backends/local/#command-line-arguments) . Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu console`. This command also accepts the following options for tofu console: * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/console/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. Remote State[​](https://opentofu.org/docs/v1.11/cli/commands/console/#remote-state "Direct link to Remote State") ------------------------------------------------------------------------------------------------------------------ If [remote state](https://opentofu.org/docs/v1.11/language/state/remote/) is used by the current backend, OpenTofu will read the state for the current workspace from the backend before evaluating any expressions. Examples[​](https://opentofu.org/docs/v1.11/cli/commands/console/#examples "Direct link to Examples") ------------------------------------------------------------------------------------------------------ The `tofu console` command will read the OpenTofu configuration in the current working directory and the OpenTofu state file from the configured backend so that interpolations can be tested against both the values in the configuration and the state file. With the following `main.tf`: Code Block variable "apps" { type = map(any) default = { "foo" = { "region" = "us-east-1", }, "bar" = { "region" = "eu-west-1", }, "baz" = { "region" = "ap-south-1", }, }}resource "random_pet" "example" { for_each = var.apps} Executing `tofu console` will drop you into an interactive shell where you can test interpolations to: Print a value from a map: Code Block > var.apps.foo{ "region" = "us-east-1"} Filter a map based on a specific value: Code Block > { for key, value in var.apps : key => value if value.region == "us-east-1" }{ "foo" = { "region" = "us-east-1" }} Check if certain values may not be known until apply: Code Block > random_pet.example(known after apply) Test various functions: Code Block > cidrnetmask("172.16.0.0/12")"255.240.0.0" * [Usage](https://opentofu.org/docs/v1.11/cli/commands/console/#usage) * [Remote State](https://opentofu.org/docs/v1.11/cli/commands/console/#remote-state) * [Examples](https://opentofu.org/docs/v1.11/cli/commands/console/#examples) --- # Command: output | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/output/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: output =============== The `tofu output` command is used to extract the value of an output variable from the state file. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/output/#usage "Direct link to Usage") -------------------------------------------------------------------------------------------- Usage: `tofu output [options] [NAME]` With no additional arguments, `output` will display all the outputs for the root module. If an output `NAME` is specified, only the value of that output is printed. Note Use of variables in [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu output`. The command-line flags are all optional. The following flags are available: * `-json` - If specified, the outputs are formatted as a JSON object, with a key per output. If `NAME` is specified, only the output specified will be returned. This can be piped into tools such as `jq` for further processing. * `-raw` - If specified, OpenTofu will convert the specified output value to a string and print that string directly to the output, without any special formatting. This can be convenient when working with shell scripts, but it only supports string, number, and boolean values. Use `-json` instead for processing complex data types. * `-no-color` - If specified, output won't contain any color. * `-state=path` - Path to the state file. Defaults to "terraform.tfstate". Ignored when [remote state](https://opentofu.org/docs/v1.11/language/state/remote/) is used. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. * `-show-sensitive` - If specified, sensitive values will be displayed. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. Note When using the `-json` or `-raw` command-line flag, any sensitive values in OpenTofu state will be displayed in plain text. For more information, see [Sensitive Data in State](https://opentofu.org/docs/v1.11/language/state/sensitive-data/) . Examples[​](https://opentofu.org/docs/v1.11/cli/commands/output/#examples "Direct link to Examples") ----------------------------------------------------------------------------------------------------- These examples assume the following OpenTofu output snippet. Code Block output "instance_ips" { value = aws_instance.web.*.public_ip}output "lb_address" { value = aws_alb.web.public_dns}output "password" { sensitive = true value = var.secret_password} To list all outputs: Code Block $ tofu outputinstance_ips = [ "54.43.114.12", "52.122.13.4", "52.4.116.53"]lb_address = "my-app-alb-1657023003.us-east-1.elb.amazonaws.com"password = Note that outputs with the `sensitive` attribute will be redacted: Code Block $ tofu output passwordpassword = To query for the DNS address of the load balancer: Code Block $ tofu output lb_address"my-app-alb-1657023003.us-east-1.elb.amazonaws.com" To query for all instance IP addresses: Code Block $ tofu output instance_ipsinstance_ips = [ "54.43.114.12", "52.122.13.4", "52.4.116.53"] Use in automation[​](https://opentofu.org/docs/v1.11/cli/commands/output/#use-in-automation "Direct link to Use in automation") -------------------------------------------------------------------------------------------------------------------------------- The `tofu output` command by default displays in a human-readable format, which can change over time to improve clarity. For scripting and automation, use `-json` to produce the stable JSON format. You can parse the output using a JSON command-line parser such as [jq](https://stedolan.github.io/jq/) : Code Block $ tofu output -json instance_ips | jq -r '.[0]'54.43.114.12 For the common case of directly using a string value in a shell script, you can use `-raw` instead, which will print the string directly with no extra escaping or whitespace. Code Block $ tofu output -raw lb_addressmy-app-alb-1657023003.us-east-1.elb.amazonaws.com The `-raw` option works only with values that OpenTofu can automatically convert to strings. Use `-json` instead, possibly combined with `jq`, to work with complex-typed values such as objects. OpenTofu strings are sequences of Unicode characters rather than raw bytes, so the `-raw` output will be UTF-8 encoded when it contains non-ASCII characters. If you need a different character encoding, use a separate command such as `iconv` to transcode OpenTofu's raw output. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/output/#usage) * [Examples](https://opentofu.org/docs/v1.11/cli/commands/output/#examples) * [Use in automation](https://opentofu.org/docs/v1.11/cli/commands/output/#use-in-automation) --- # Command: providers schema | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: providers schema ========================= The `tofu providers schema` command is used to print detailed schemas for the providers used in the current configuration. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------------ Usage: `tofu providers schema [options]` Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu providers schema`. The following flags are available: * `-json` - Displays the schemas in a machine-readable, JSON format. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. Please note that, at this time, the `-json` flag is a _required_ option. In future releases, this command will be extended to allow for additional options. The output includes a `format_version` key, which has value `"1.0"`. The semantics of this version are: * We will increment the minor version, e.g. `"1.1"`, for backward-compatible changes or additions. Ignore any object properties with unrecognized names to remain forward-compatible with future minor versions. * We will increment the major version, e.g. `"2.0"`, for changes that are not backward-compatible. Reject any input which reports an unsupported major version. We will introduce new major versions only within the bounds of [the OpenTofu 1.0 Compatibility Promises](https://opentofu.org/docs/v1.11/language/v1-compatibility-promises/) . Format Summary[​](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#format-summary "Direct link to Format Summary") --------------------------------------------------------------------------------------------------------------------------------- The following sections describe the JSON output format by example, using a pseudo-JSON notation. Important elements are described with comments, which are prefixed with //. To avoid excessive repetition, we've split the complete format into several discrete sub-objects, described under separate headers. References wrapped in angle brackets (like ``) are placeholders which, in the real output, would be replaced by an instance of the specified sub-object. The JSON output format consists of the following objects and sub-objects: * [Providers Schema Representation](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#providers-schema-representation) - the top-level object returned by `tofu providers schema -json` * [Schema Representation](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#schema-representation) - a sub-object of providers, resources, and data sources that describes their schema * [Block Representation](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#block-representation) - a sub-object of schemas that describes attributes and nested blocks Providers Schema Representation[​](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#providers-schema-representation "Direct link to Providers Schema Representation") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Code Block { "format_version": "1.0", // "provider_schemas" describes the provider schemas for all // providers throughout the configuration tree. "provider_schemas": { // keys in this map are the provider type, such as "random" "example_provider_name": { // "provider" is the schema for the provider configuration "provider": , // "resource_schemas" map the resource type name to the resource's schema "resource_schemas": { "example_resource_name": }, // "data_source_schemas" map the data source type name to the // data source's schema "data_source_schemas": { "example_datasource_name": , } }, "example_provider_two": { … } }} Schema Representation[​](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#schema-representation "Direct link to Schema Representation") ------------------------------------------------------------------------------------------------------------------------------------------------------ A schema representation pairs a provider or resource schema (in a "block") with that schema's version. Code Block { // "version" is the schema version, not the provider version "version": int64, "block": } Block Representation[​](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#block-representation "Direct link to Block Representation") --------------------------------------------------------------------------------------------------------------------------------------------------- A block representation contains "attributes" and "block\_types" (which represent nested blocks). Code Block { // "attributes" describes any attributes that appear directly inside the // block. Keys in this map are the attribute names. "attributes": { "example_attribute_name": { // "type" is a representation of a type specification // that the attribute's value must conform to. "type": "string", // "description" is an English-language description of // the purpose and usage of the attribute. "description": "string", // "required", if set to true, specifies that an // omitted or null value is not permitted. "required": bool, // "optional", if set to true, specifies that an // omitted or null value is permitted. "optional": bool, // "computed", if set to true, indicates that the // value comes from the provider rather than the // configuration. "computed": bool, // "sensitive", if set to true, indicates that the // attribute may contain sensitive information. "sensitive": bool }, }, // "block_types" describes any nested blocks that appear directly // inside the block. // Keys in this map are the names of the block_type. "block_types": { "example_block_name": { // "nesting_mode" describes the nesting mode for the // child block, and can be one of the following: // single // list // set // map "nesting_mode": "list", "block": , // "min_items" and "max_items" set lower and upper // limits on the number of child blocks allowed for // the list and set modes. These are // omitted for other modes. "min_items": 1, "max_items": 3 }} * [Usage](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#usage) * [Format Summary](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#format-summary) * [Providers Schema Representation](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#providers-schema-representation) * [Schema Representation](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#schema-representation) * [Block Representation](https://opentofu.org/docs/v1.11/cli/commands/providers/schema/#block-representation) --- # OpenTofu v1.x Compatibility Promises | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page OpenTofu v1.x Compatibility Promises ==================================== The release of OpenTofu v1.6 represents an important milestone in the development of the OpenTofu language and workflow. OpenTofu v1.x is a stable platform for describing and managing infrastructure. In this release we're defining a number of OpenTofu behaviors that we intend to remain compatible with throughout the 1.x releases: * A large subset of OpenTofu language features. * A more conservative subset of the OpenTofu CLI workflow commands. * The wire protocol for communication between OpenTofu Core and OpenTofu providers. * The wire protocols for installation of providers and external modules. Our intention is that modules written for OpenTofu v1.6 will continue to plan and apply successfully, without required changes, throughout the v1.x releases. We also intend that automation built around the workflow subset described in this document will work without changes in all future v1.x releases. Finally, we intend that providers built against the currently-documented provider wire protocol will be compatible with all future OpenTofu v1.x releases targeting the same operating system and architecture, without the need for source code modification or binary recompilation. In short, we aim to make upgrades between v1.x releases straightforward, requiring no changes to your configuration, no extra commands to run upgrade steps, and no changes to any automation you've set up around OpenTofu. The OpenTofu v1.x series will be actively maintained for at least 18 months after v1.6. The following sections include some specific guidance on what we will promise throughout the v1.x series, for those who would like full details. At a higher level though, we don't intend to make any changes that would cause existing modules or automation to require changes when upgrading to a new v1.x release. We will generally treat compatibility problems in new OpenTofu CLI releases as bugs to be fixed unless there was a very significant justification for the change, such as in addressing a critical security problem or matching with a breaking change to a remote dependency that isn't directly under our control. The OpenTofu Language[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#the-opentofu-language "Direct link to The OpenTofu Language") ----------------------------------------------------------------------------------------------------------------------------------------------------------- The main OpenTofu Language includes the language syntax, the top-level structures such as `resource`, `module`, and `provider` blocks, the "meta-arguments" in those blocks, and the documented semantics and behaviors for the operators and built-in functions available for use in expressions. There is not a single formal specification for the OpenTofu language, but the Configuration section of the documentation on the OpenTofu website serves as a description of the language features and their intended behaviors. The following top-level blocks and their defined "meta-arguments" (that is, arguments defined by OpenTofu Core rather than by external plugins such as providers) will retain their current functionality: * [`resource`](https://opentofu.org/docs/v1.10/language/resources/) and [`data`](https://opentofu.org/docs/v1.10/language/data-sources/) blocks to declare resources, including their nested block types `lifecycle`, `connection`, and `provisioner`, and their meta-argument `provider`. * [`module`](https://opentofu.org/docs/v1.10/language/modules/syntax/) blocks to call other modules, and its meta-argument `providers`. * The [`count`](https://opentofu.org/docs/v1.10/language/meta-arguments/count/) , [`for_each`](https://opentofu.org/docs/v1.10/language/meta-arguments/for_each/) , and [`depends_on`](https://opentofu.org/docs/v1.10/language/meta-arguments/depends_on/) meta-arguments in `resource`, `data`, and `module` blocks. * [`provider`](https://opentofu.org/docs/v1.10/language/providers/configuration/) blocks to configure providers, and the `alias` meta-argument. * [`variable`](https://opentofu.org/docs/v1.10/language/values/variables/#declaring-an-input-variable) , [`output`](https://opentofu.org/docs/v1.10/language/values/outputs/#declaring-an-output-value) , and [`locals`](https://opentofu.org/docs/v1.10/language/values/locals/#declaring-a-local-value) blocks for declaring the various kinds of named values in a module. * [`terraform`](https://opentofu.org/docs/v1.10/language/settings/) blocks, including the nested [`required_version`](https://opentofu.org/docs/v1.10/language/settings/#specifying-a-required-tofu-version) and [`required_providers`](https://opentofu.org/docs/v1.10/language/providers/requirements/#requiring-providers) arguments, and nested [`backend`](https://opentofu.org/docs/v1.10/language/settings/backends/configuration/#using-a-backend-block) blocks for backend configuration. We also intend to keep compatibility with all [expression operators](https://opentofu.org/docs/v1.10/language/expressions/) and [built-in functions](https://opentofu.org/docs/v1.10/language/functions/) , with the exception of references to [`terraform.workspace`](https://opentofu.org/docs/v1.10/language/expressions/references/#terraform-workspace) , whose behavior may change as part of future changes to the workspace model. We intend to retain broad compatibility with OpenTofu language features, with a few specific caveats: * We consider a configuration to be valid if OpenTofu can create and apply a plan for it without reporting any errors. A configuration that currently produces errors might generate different errors or exhibit other non-error behaviors in a future version of OpenTofu. A configuration that generates errors during the apply phase might generate similar errors at an earlier phase in future, because we generally consider it better to detect errors in as early a phase as possible. Generally-speaking, the compatibility promises described in this document apply only to valid configurations. Handling of invalid configurations is always subject to change in future OpenTofu releases. * If the actual behavior of a feature differs from what we explicitly documented as the feature's behavior, we will usually treat that as a bug and change the feature to match the documentation, although we will avoid making such changes if they seem likely to cause broad compatibility problems. We cannot promise to always remain "bug-compatible" with previous releases, but we will consider such fixes carefully to minimize their impact. * Any experimental features may change or may be removed entirely from future releases. OpenTofu always produces a warning when an experimental language feature is active, to make you aware of that risk. We don't recommend using experimental features in production modules. * We will introduce new language features, and if you start using them then your configuration won't work with prior OpenTofu versions that didn't support those features yet. * Providers are separate plugins which can change independently of OpenTofu Core and are therefore not subject to these compatibility promises. If you upgrade any of the providers you are using then you might need to change provider or resource configurations related to those providers. * A small number of features remain deprecated with explicit warnings in OpenTofu v1.6. Those deprecation cycles will end in a future v1.x release, at which point we will remove the corresponding features. Workflow[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#workflow "Direct link to Workflow") -------------------------------------------------------------------------------------------------------------------- There is a set of often used OpenTofu workflows, which we are calling _protected workflows_. We will not remove these commands, subcommands, and flags or make backward-incompatible changes to protected workflow functionality. If we accidentally change these, we will consider backwards-incompatible changes to core workflows as bugs to be fixed. For a list of the command and option combinations that are part of protected workflows, see [Protected Workflow Commands](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#protected-workflow-commands) . There is another set of commands that we are explicitly _not_ making compatibility promises about, because we expect their functionality to change in v1.x releases: see [Commands That Might Change](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#commands-that-might-change) . The supported ways for external software to interact with OpenTofu are via the JSON output modes offered by some commands and via exit status codes. We may extend certain JSON formats with new object properties but we will not remove or make breaking changes to the definitions of existing properties. Natural language command output or log output is not a stable interface and may change in any new version. If you write software that parses this output then it may need to be updated when you upgrade OpenTofu. If you need access to data that is not currently available via one of the machine-readable JSON interfaces, we suggest opening a feature request to discuss your use-case. Upgrading and Downgrading[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#upgrading-and-downgrading "Direct link to Upgrading and Downgrading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Throughout the v1.x series of releases, we intend that you should be able to switch to a newer OpenTofu version and use it just as before, without any special upgrade steps. You should be able to upgrade from any v1.x release to any later v1.x release. You might also be able to downgrade to an earlier v1.x release, but that isn't guaranteed: later releases may introduce new features that earlier versions cannot understand, including new storage formats for OpenTofu state snapshots. If you make use of features introduced in a later v1.x release, your configuration won't be compatible with releases that predate that feature. For example, if a language feature is added in v1.7 and you start using it, your OpenTofu configuration will no longer be compatible with OpenTofu v1.6. Providers[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#providers "Direct link to Providers") ----------------------------------------------------------------------------------------------------------------------- OpenTofu providers are separate plugins which communicate with OpenTofu using a documented protocol. Therefore these compatibility promises can only cover the "client" side of this protocol as implemented by OpenTofu Core; the behaviors of individual providers, including which resource types they support and which arguments they expect, are decided by the provider development teams and can change independently of OpenTofu Core releases. If you upgrade to a new version of a provider then you might need to change the parts of your configuration which are interpreted by that provider, even if you are still using an OpenTofu v1.x release. ### Provider Installation Methods[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#provider-installation-methods "Direct link to Provider Installation Methods") OpenTofu normally installs providers from a provider registry implementing [the Provider Registry Protocol](https://opentofu.org/docs/v1.10/internals/provider-registry-protocol/) , version 1. All OpenTofu v1.x releases will remain compatible with that protocol, and so correctly-implemented provider registries will stay compatible. OpenTofu also supports installation of providers from [local filesystem directories](https://opentofu.org/docs/v1.10/cli/config/config-file/#filesystem_mirror) (filesystem mirrors) and from [network mirrors](https://opentofu.org/docs/v1.10/cli/config/config-file/#network_mirror) (implementing [the Provider Mirror Protocol](https://opentofu.org/docs/v1.10/internals/provider-network-mirror-protocol/) . All OpenTofu v1.x releases will remain compatible with those installation methods, including [the Implied Local Mirror Directories](https://opentofu.org/docs/v1.10/cli/config/config-file/#implied-local-mirror-directories) . Specific provider registries or network mirrors are run independently from OpenTofu itself and so their own behaviors are not subject to these compatibility promises. ### Provider Protocol Versions[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#provider-protocol-versions "Direct link to Provider Protocol Versions") The current major version of the provider plugin protocol as of OpenTofu v1.6 is version 5, which is defined by a combination of a Protocol Buffers schema describing the physical wire formats and by additional prose documentation describing the expected provider behaviors. We will support protocol version 5 throughout the OpenTofu v1.x releases. If we make new minor revisions to protocol version 5 in later releases then we will design them such that existing plugins will continue to work, as long as they correctly implemented the protocol. We may introduce new major versions of the protocol during the v1.x series. If so, we will continue to support protocol version 5 alongside those new versions. Individual provider teams might decide to remove support for protocol version 5 in later releases, in which case those new provider releases will not be compatible with all of the OpenTofu v1.x releases. External Modules[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#external-modules "Direct link to External Modules") -------------------------------------------------------------------------------------------------------------------------------------------- Modules are reusable infrastructure components written in the OpenTofu language. Some modules are "external" in the sense that OpenTofu automatically installs them from a location other than the current configuration directory, in which case their contents could change independently of changes to your local modules, of the providers you use, and of OpenTofu itself. ### Module Installation Methods[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#module-installation-methods "Direct link to Module Installation Methods") OpenTofu supports installing child modules from a number of different [module source types](https://opentofu.org/docs/v1.10/language/modules/sources/) . We will continue to support all of the existing source types throughout the v1.x releases. One of the supported source types is a module registry implementing [the Module Registry Protocol](https://opentofu.org/docs/v1.10/internals/module-registry-protocol/) version 1. All OpenTofu v1.x releases will remain compatible with correct implementations of that protocol. Some module source types work directly with services or protocols defined and run by third parties. Although we will not remove OpenTofu's own client-side support for those, we cannot guarantee that their owners will keep those services running or that they will remain compatible with OpenTofu's client implementations. ### External Module Compatibility[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#external-module-compatibility "Direct link to External Module Compatibility") If your configuration depends on external modules, newer versions of those modules may include breaking changes. External modules are not part of OpenTofu and are therefore not subject to these compatibility promises. Provisioners[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#provisioners "Direct link to Provisioners") -------------------------------------------------------------------------------------------------------------------------------- We will maintain compatibility for the `file`, `local-exec`, and `remote-exec` provisioner types through all v1.x releases. OpenTofu supports loading additional provisioners as plugins from certain local filesystem directories. We'll continue to support that throughout the OpenTofu v1.x releases, but since such plugins are separate from OpenTofu Core itself their own behaviors cannot be subject to these compatibility promises. However, we will continue to support the plugin wire protocol as defined in OpenTofu v1.6 throughout the v1.x releases, and so correctly-implemented provisioner plugins should remain compatible with future OpenTofu releases. State Storage Backends[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#state-storage-backends "Direct link to State Storage Backends") -------------------------------------------------------------------------------------------------------------------------------------------------------------- When you use _remote state_, OpenTofu interacts with remote services over the network in order to store and manage locks for OpenTofu state. For historical reasons, all supported state storage backends are included as part of OpenTofu CLI but not all are supported directly by the OpenTofu Team. Only the following backends maintained by the OpenTofu team are subject to compatibility promises: * `local` (the default, when you are not using remote state) * `http` The other state storage backends are maintained by external teams via contributions to the OpenTofu CLI codebase, and so their expected configuration arguments or behaviors might change even in v1.x releases, although we will aim to still ensure a good migration path in such cases, where possible. We are considering allowing external state storage backend implementations via plugins, similar to provider plugins. If we introduce such a mechanism during the v1.x releases then you may need to make configuration changes in order to use those plugins, and state storage backends other than those listed above may be removed from later versions of OpenTofu CLI once equivalent plugins are available. ### The `remote` Backend[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#the-remote-backend "Direct link to the-remote-backend") The `remote` backend's behavior may change along the way and is therefore not subject to these compatibility promises. Community-maintained State Storage Backends[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#community-maintained-state-storage-backends "Direct link to Community-maintained State Storage Backends") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The `azurerm`, `consul`, `s3`, and `kubernetes` backends are maintained by other teams at HashiCorp. Those teams intend to continue basic maintenance at the level of bug fixes through the v1.x releases, unless we implement a plugin protocol for backends at which point development of these backends is likely to continue in the external plugins only, which may require configuration changes to switch to the plugin equivalents. The `cos`, `oss`, `pg`, `gcs`, and `etcdv3` backends are maintained by outside contributors and are not subject to these compatibility promises. ### Unmaintained State Storage Backends[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#unmaintained-state-storage-backends "Direct link to Unmaintained State Storage Backends") The `artifactory`, `etcdv2`, `manta`, and `swift` state storage backends do not currently have any maintainers and thus remain in OpenTofu CLI releases on a best-effort basis. They may be removed in later v1.x releases, and will not be updated in case of any breaking changes to the services they integrate with. Supported Platforms[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#supported-platforms "Direct link to Supported Platforms") ----------------------------------------------------------------------------------------------------------------------------------------------------- Throughout the v1.x series we will continue to produce official releases for the following platforms, and make changes as necessary to support new releases of these operating systems: * macOS on x64 CPUs (`darwin_amd64`) * Windows on x64 CPUs (`windows_amd64`) * Linux on x64, 32-bit ARMv6, and 64-bit ARMv8 (`linux_amd64`, `linux_arm`, and `linux_arm64` respectively) Over time we may require newer versions of these operating systems. For example, subsequent OpenTofu releases in the v1.x series might end support for earlier versions of macOS or Windows, or earlier Linux kernel releases. We have historically produced official releases for a number of other platforms as a convenience to users of those platforms, and we have no current plans to stop publishing them but we cannot promise ongoing releases or bug fixes for the other platforms throughout the v1.x series. We do not routinely test OpenTofu on any platforms other than those listed above. We might add support for new platforms in later v1.x releases. If so, earlier OpenTofu releases prior to that support will not be available on those platforms. All OpenTofu plugins, including provider plugins, are separate programs that have their own policies for which platforms they support. We cannot guarantee that all providers currently support or will continue to support the platforms listed above, even though OpenTofu CLI itself will support them. Later Revisions to These Promises[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#later-revisions-to-these-promises "Direct link to Later Revisions to These Promises") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- We may extend or refine these promises throughout the v1.x series in order to describe promises related to new features or to clarify existing promises if we find via feedback that our earlier statements had been unclear. Promises for new features will be additive in the sense that they will add further promises without retracting any existing ones. For promises that only apply to later v1.x releases we will mention the earliest version(s) those promises apply to. Even if we don't add an explicit statement to this document, we intend that any non-experimental features added in later v1.x releases will remain compatible at least through the remainder of the v1.x series, unless otherwise stated. Appendices[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#appendices "Direct link to Appendices") -------------------------------------------------------------------------------------------------------------------------- ### Protected Workflow Commands[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#protected-workflow-commands "Direct link to Protected Workflow Commands") The following is the list of OpenTofu CLI subcommands and options that are subject to these compatibility promises. If you build automation around these commands then it should be compatible with all later v1.x releases. As noted above, compatibility with external software is limited to explicitly-machine-readable output (`-json` and `-raw` modes) and exit codes. Any natural-language output from these commands might change in later releases. * [`init`](https://opentofu.org/docs/v1.10/cli/commands/init/) * `-backend=false` * `-backend-config=FILE` * `-backend-config="KEY=VALUE"` * `-force-copy` * `-get=false` * `-input=false` * `-migrate-state` * `-no-color` * `-plugin-dir=DIR` * `-reconfigure` * `-upgrade` * [`validate`](https://opentofu.org/docs/v1.10/cli/commands/validate/) * `-json` * `-no-color` * [`plan`](https://opentofu.org/docs/v1.10/cli/commands/plan/) * `-compact-warnings` * `-destroy` * `-detailed-exitcode` * `-lock=false` * `-lock-timeout=DURATION` * `-input=false` * `-json` * `-no-color` * `-out=FILE` * `-parallelism=N` * `-refresh=false` * `-refresh-only` * `-replace=ADDRESS` * `-target=ADDRESS` * `-var 'NAME=VALUE'` * `-var-file=FILE` * [`apply`](https://opentofu.org/docs/v1.10/cli/commands/apply/) * `-auto-approve` * `-compact-warnings` * `-lock=false` * `-lock-timeout=DURATION` * `-input=false` * `-json` * `-no-color` * `-parallelism=N` * `-refresh=false` * `-refresh-only` * `-replace=ADDRESS` * `-target=ADDRESS` * `-var 'NAME=VALUE'` * `-var-file=FILE` * [`show`](https://opentofu.org/docs/v1.10/cli/commands/show/) * `-no-color` * `-json` * (both with and without a plan file) * [`providers`](https://opentofu.org/docs/v1.10/cli/commands/providers/) (with no subcommand) * [`providers lock`](https://opentofu.org/docs/v1.10/cli/commands/providers/lock/) * `-fs-mirror=PATH` * `-net-mirror=URL` * `-platform=OS_ARCH` * [`providers mirror`](https://opentofu.org/docs/v1.10/cli/commands/providers/mirror/) * `-platform=OS_ARCH` * [`providers schema`](https://opentofu.org/docs/v1.10/cli/commands/providers/schema/) * `-json` * [`fmt`](https://opentofu.org/docs/v1.10/cli/commands/fmt/) * `-list=false` * `-write=false` * `-diff` * `-recursive` * `-check` * [`version`](https://opentofu.org/docs/v1.10/cli/commands/version/) * `-json` * [`output`](https://opentofu.org/docs/v1.10/cli/commands/output/) * `-no-color` * `-json` * `-raw` * [`taint`](https://opentofu.org/docs/v1.10/cli/commands/taint/) * `-allow-missing` * `-lock=false` * `-lock-timeout=DURATION` * `-ignore-remote-version` * [`untaint`](https://opentofu.org/docs/v1.10/cli/commands/untaint/) * `-allow-missing` * `-lock=false` * `-lock-timeout=DURATION` * `-ignore-remote-version` * [`force-unlock`](https://opentofu.org/docs/v1.10/cli/commands/force-unlock/) * `-force` * [`state list`](https://opentofu.org/docs/v1.10/cli/commands/state/list/) * `-id=ID` * [`state pull`](https://opentofu.org/docs/v1.10/cli/commands/state/pull/) * [`state push`](https://opentofu.org/docs/v1.10/cli/commands/state/push/) * `-force` * `-lock=false` * `-lock-timeout=DURATION` * [`state show`](https://opentofu.org/docs/v1.10/cli/commands/state/show/) * `-ignore-remote-version` * [`login`](https://opentofu.org/docs/v1.10/cli/commands/login/) For commands or options not in the above list, we will still avoid breaking changes where possible, but can't promise full compatibility throughout the v1.x series. If you are building automation around OpenTofu, use only the commands above to avoid the need for changes when upgrading. Please note that although OpenTofu's internal logs (via the `TF_LOG` environment variable) are available in a JSON format, the particular syntax or structure of those log lines is _not_ a supported integration interface. The logs are available as JSON only to help with ad-hoc filtering and processing of logs by OpenTofu developers. ### Commands That Might Change[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#commands-that-might-change "Direct link to Commands That Might Change") All of the following commands and their subcommands/options are _not_ subject to compatibility promises, either because we have existing plans to improve them during the v1.x series or because we are aware of shortcomings in their design that might require breaking changes for ongoing maintenance. While you can freely use these commands when running OpenTofu interactively as long as they remain supported, we don't recommend using them as part of any automation unless you are willing to potentially update that automation when upgrading to a later v1.x release. * `destroy` (consider `tofu apply -destroy` instead) * `console` * `get` (consider `tofu init` instead) * `graph` * `import` * `push` * `refresh` (consider `tofu apply -refresh-only` instead) * `state mv` * `state replace-provider` * `state rm` * all subcommands of `workspace` (and its deprecated alias `env`) While we do intend to retain support for the main use-cases associated with these commands in future releases, we cannot promise to retain the exact command names or options used to meet those use-cases. How We Will Keep These Promises[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#how-we-will-keep-these-promises "Direct link to How We Will Keep These Promises") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### Automated Regression Testing[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#automated-regression-testing "Direct link to Automated Regression Testing") The OpenTofu codebase includes various unit and integration tests intended to help us to notice accidental behavior regressions before they ship in a stable version. However, OpenTofu is a relatively complex system with many different features that can interact in interesting ways. In the past we've seen reports of behavior differences that appeared only when combining two or more features in a way we hadn't previously anticipated or written automated tests for. In each case we have both implemented a change to resolve the compatibility problem _and_ added one or more integration tests representing the behavior of that combination of features. We intend to continue this approach, so we can improve OpenTofu's test coverage over time. ### Prerelease Versions[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#prerelease-versions "Direct link to Prerelease Versions") We intend that most accidental changes in behavior covered by these promises will be caught by existing tests. However, we also accept that our test suite can never have perfect coverage of all possible feature interactions or other edge cases, and so we aim for each significant change to be included in both alpha and beta releases before eventual inclusion in a final release. For minor releases we will typically also issue at least one release candidate prior to the final release. A release candidate represents that planned development is concluded and that we've fixed any regressions reported based on the alpha and beta releases, and thus the final release that follows should typically match exactly or almost exactly its most recent release candidate. ### Regressions in Final Releases[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#regressions-in-final-releases "Direct link to Regressions in Final Releases") For more obscure combinations of features it is possible that a regression could be undetected during prerelease the prerelease periods and thus included in a final release. If someone finds and reports such a regression soon after its release then we will treat it as a bug and fix it to restore the previous behavior in future releases, unless there is a very significant justification such as a security advisory. In these cases, we'll typically recommend anyone affected by the regression remain on the previous version until the problem is fixed and then skip forward directly to the new release containing that fix. You can minimize the risk of being affected by missed regressions in final releases by proactively testing modules against alpha, beta, and release candidate packages. We recommend doing so only in isolated development or staging environments rather than against your production infrastructure. If you find a change in behavior in a prerelease build that seems contrary to the promises in this document, please open an issue in OpenTofu's GitHub repository to discuss it. ### Late-reported Regressions[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#late-reported-regressions "Direct link to Late-reported Regressions") In the most extreme case, there may be a regression with a combination of features that is so rare that it remains undetected for a long time. After a change has been included in more releases it becomes increasingly likely that other users will have depended on the newer behavior and thus we will need to make a tradeoff to decide whether restoring the behavior would have a greater negative impact than retaining the new behavior. We will always make this decision with due consideration to the implications of each unique situation. You can minimize the risk of your modules being affected by late-reported regressions by upgrading promptly to new minor and patch releases of OpenTofu and reporting any compatibility problems you encounter in OpenTofu's GitHub repository. ### Pragmatic Exceptions[​](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#pragmatic-exceptions "Direct link to Pragmatic Exceptions") We are making the promises above in good faith, with the intent that your investment in writing OpenTofu modules or automation will not be invalidated by future changes to OpenTofu. However, broad promises like the above can't possibly cover all nuances of practical problems that might arise as we continue to develop OpenTofu. For that reason, there are some situations where we may still need to make changes that may impact existing modules or automation: * Security problems: We may become aware of a design problem that has an important security impact. Depending on our determination of the associated risk, we may choose to break compatibility to achieve a more secure system. * External Dependencies: OpenTofu's behavior depends on interfaces provided by external codebases, including your chosen operating system and including some remote network services for situations such as module and provider installation. These external systems can change outside of our control, including potentially removing or changing features that OpenTofu's own features depend on. In that case, if there is no suitable replacement mechanism then we may need to change OpenTofu's design to work within the new constraints. * Opt-in Compatibility Breaks: The design of a language new feature may require changing the behavior or configuration representation of an existing feature. If so, we will typically make the new feature opt-in only in order to avoid breaking existing modules, but if you change your module to opt in to the new feature then you may also then be required to change other parts of your configuration to work with the new language design. * Bugs in New Features: If we introduce a new feature to OpenTofu and the initial implementation has problems that cause it to not match the documented design intent at release, we may make a follow-up release that corrects the implementation to match the documented design, even if that represents a minor compatibility regression compared to the initial implementation. However, once a feature is well-established and in common use we will usually defer to the implemented behavior and instead change the documentation to reflect it. * Regressions in Existing Features: If we learn that a new OpenTofu release includes a regression for an existing feature that wasn't detected during the development and prerelease periods, and that learning comes promptly after the new release, we will typically restore the previous behavior at the expense of technically therefore breaking compatibility with the behavior of the new release, under the assumption that more users will have systems affected by the regression than will have systems depending on the newly-introduced behavior. * Late-reported regressions: As described in the previous section, if we learn that there was an unintentional regression of a rarely-used feature or combination of features in a much earlier release then restoring the previous behavior may appear as a regression to later adopters. If we believe that fixing the regression would affect more users than the regression itself affects then we may choose to accept the regression as the new promised behavior. * Situations we cannot anticipate: Although we've made an effort to consider various specific exceptional situations here, OpenTofu and its development process are not isolated from broader context, and so we must consider that there may be situations that we cannot possibly anticipate that would affect the future of OpenTofu. In those situations, we will always do our best to find a course of action that will minimize as much as possible the impact to existing modules and automation. Our intent with these pragmatic exceptions is only to acknowledge that there will always be situations that general compatibility promises cannot address. We will use these exceptions only with due consideration and as a last resort. * [The OpenTofu Language](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#the-opentofu-language) * [Workflow](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#workflow) * [Upgrading and Downgrading](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#upgrading-and-downgrading) * [Providers](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#providers) * [Provider Installation Methods](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#provider-installation-methods) * [Provider Protocol Versions](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#provider-protocol-versions) * [External Modules](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#external-modules) * [Module Installation Methods](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#module-installation-methods) * [External Module Compatibility](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#external-module-compatibility) * [Provisioners](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#provisioners) * [State Storage Backends](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#state-storage-backends) * [The `remote` Backend](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#the-remote-backend) * [Community-maintained State Storage Backends](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#community-maintained-state-storage-backends) * [Unmaintained State Storage Backends](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#unmaintained-state-storage-backends) * [Supported Platforms](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#supported-platforms) * [Later Revisions to These Promises](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#later-revisions-to-these-promises) * [Appendices](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#appendices) * [Protected Workflow Commands](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#protected-workflow-commands) * [Commands That Might Change](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#commands-that-might-change) * [How We Will Keep These Promises](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#how-we-will-keep-these-promises) * [Automated Regression Testing](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#automated-regression-testing) * [Prerelease Versions](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#prerelease-versions) * [Regressions in Final Releases](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#regressions-in-final-releases) * [Late-reported Regressions](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#late-reported-regressions) * [Pragmatic Exceptions](https://opentofu.org/docs/v1.10/language/v1-compatibility-promises/#pragmatic-exceptions) --- # Version Constraints | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Version Constraints =================== Anywhere that OpenTofu lets you specify a range of acceptable versions for something, it expects a specially formatted string known as a version constraint. Version constraints are used when configuring: * [Modules](https://opentofu.org/docs/v1.11/language/modules/) * [Provider requirements](https://opentofu.org/docs/v1.11/language/providers/requirements/) * [The `required_version` setting](https://opentofu.org/docs/v1.11/language/settings/#specifying-a-required-tofu-version) in the `terraform` block. Version Constraint Syntax[​](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#version-constraint-syntax "Direct link to Version Constraint Syntax") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu's syntax for version constraints is very similar to the syntax used by other dependency management systems like Bundler and NPM. Code Block version = ">= 1.2.0, < 2.0.0" A version constraint is a [string literal](https://opentofu.org/docs/v1.11/language/expressions/strings/) containing one or more conditions, which are separated by commas. Each condition consists of an operator and a version number. Version numbers should be a series of numbers separated by periods (like `1.2.0`), optionally with a suffix to indicate a beta release. The following operators are valid: * `=` (or no operator): Allows only one exact version number. Cannot be combined with other conditions. * `!=`: Excludes an exact version number. * `>`, `>=`, `<`, `<=`: Comparisons against a specified version, allowing versions for which the comparison is true. "Greater-than" requests newer versions, and "less-than" requests older versions. * `~>`: Allows only the _rightmost_ version component to increment. For example, to allow new patch releases within a specific minor release, use the full version number: `~> 1.0.4` will allow installation of `1.0.5` and `1.0.10` but not `1.1.0`. This is usually called the pessimistic constraint operator. Version Constraint Behavior[​](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#version-constraint-behavior "Direct link to Version Constraint Behavior") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A version number that meets every applicable constraint is considered acceptable. OpenTofu consults version constraints to determine whether it has acceptable versions of itself, any required provider plugins, and any required modules. For plugins and modules, it will use the newest installed version that meets the applicable constraints. If OpenTofu doesn't have an acceptable version of a required plugin or module, it will attempt to download the newest version that meets the applicable constraints. If OpenTofu isn't able to obtain acceptable versions of external dependencies, or if it doesn't have an acceptable version of itself, it won't proceed with any plans, applies, or state manipulation actions. Both the root module and any child module can constrain the acceptable versions of OpenTofu and any providers they use. OpenTofu considers these constraints equal, and will only proceed if all of them can be met. A prerelease version is a version number that contains a suffix introduced by a dash, like `1.2.0-beta`. A prerelease version can be selected only by an _exact_ version constraint (the `=` operator or no operator). Prerelease versions do not match inexact operators such as `>=`, `~>`, etc. Best Practices[​](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#best-practices "Direct link to Best Practices") -------------------------------------------------------------------------------------------------------------------------------------------- ### Module Versions[​](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#module-versions "Direct link to Module Versions") * When depending on third-party modules, require specific versions to ensure that updates only happen when convenient to you. * For modules maintained within your organization, specifying version ranges may be appropriate if semantic versioning is used consistently or if there is a well-defined release process that avoids unwanted updates. ### OpenTofu Core and Provider Versions[​](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#opentofu-core-and-provider-versions "Direct link to OpenTofu Core and Provider Versions") * Reusable modules should constrain only their minimum allowed versions of OpenTofu and providers, such as `>= 0.12.0`. This helps avoid known incompatibilities, while allowing the user of the module flexibility to upgrade to newer versions of OpenTofu without altering the module. * Root modules should use a `~>` constraint to set both a lower and upper bound on versions for each provider they depend on. ### Supporting both OpenTofu and Terraform Versions[​](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#supporting-both-opentofu-and-terraform-versions "Direct link to Supporting both OpenTofu and Terraform Versions") * When configuration needs to be supported by both OpenTofu and Terraform, for example in modules which need to be consumed by both engines, use a `providers.tofu` file to specify the OpenTofu version constraint, overriding the constraint defined in `providers.tf`. [Read more about extension precedence](https://opentofu.org/docs/v1.11/language/files/#extension-precedence) . * [Version Constraint Syntax](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#version-constraint-syntax) * [Version Constraint Behavior](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#version-constraint-behavior) * [Best Practices](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#best-practices) * [Module Versions](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#module-versions) * [OpenTofu Core and Provider Versions](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#opentofu-core-and-provider-versions) * [Supporting both OpenTofu and Terraform Versions](https://opentofu.org/docs/v1.11/language/expressions/version-constraints/#supporting-both-opentofu-and-terraform-versions) --- # Arithmetic and Logical Operators | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/expressions/operators/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Arithmetic and Logical Operators ================================ An _operator_ is a type of expression that transforms or combines one or more other expressions. Operators either combine two values in some way to produce a third result value, or transform a single given value to produce a single result. Operators that work on two values place an operator symbol between the two values, similar to mathematical notation: `1 + 2`. Operators that work on only one value place an operator symbol before that value, like `!true`. The OpenTofu language has a set of operators for both arithmetic and logic, which are similar to operators in programming languages such as JavaScript or Ruby. When multiple operators are used together in an expression, they are evaluated in the following order of operations: 1. `!`, `-` (multiplication by `-1`) 2. `*`, `/`, `%` 3. `+`, `-` (subtraction) 4. `>`, `>=`, `<`, `<=` 5. `==`, `!=` 6. `&&` 7. `||` Use parentheses to override the default order of operations. Without parentheses, higher levels will be evaluated first, so OpenTofu will interpret `1 + 2 * 3` as `1 + (2 * 3)` and _not_ as `(1 + 2) * 3`. The different operators can be gathered into a few different groups with similar behavior, as described below. Each group of operators expects its given values to be of a particular type. OpenTofu will attempt to convert values to the required type automatically, or will produce an error message if automatic conversion is impossible. Arithmetic Operators[​](https://opentofu.org/docs/v1.11/language/expressions/operators/#arithmetic-operators "Direct link to Arithmetic Operators") ---------------------------------------------------------------------------------------------------------------------------------------------------- The arithmetic operators all expect number values and produce number values as results: * `a + b` returns the result of adding `a` and `b` together. * `a - b` returns the result of subtracting `b` from `a`. * `a * b` returns the result of multiplying `a` and `b`. * `a / b` returns the result of dividing `a` by `b`. * `a % b` returns the remainder of dividing `a` by `b`. This operator is generally useful only when used with whole numbers. * `-a` returns the result of multiplying `a` by `-1`. OpenTofu supports some other less-common numeric operations as [functions](https://opentofu.org/docs/v1.11/language/expressions/function-calls/) . For example, you can calculate exponents using [the `pow` function](https://opentofu.org/docs/v1.11/language/functions/pow/) . Equality Operators[​](https://opentofu.org/docs/v1.11/language/expressions/operators/#equality-operators "Direct link to Equality Operators") ---------------------------------------------------------------------------------------------------------------------------------------------- The equality operators both take two values of any type and produce boolean values as results. * `a == b` returns `true` if `a` and `b` both have the same type and the same value, or `false` otherwise. * `a != b` is the opposite of `a == b`. Because the equality operators require both arguments to be of exactly the same type in order to decide equality, we recommend using these operators only with values of primitive types or using explicit type conversion functions to indicate which type you are intending to use for comparison. Comparisons between structural types may produce surprising results if you are not sure about the types of each of the arguments. For example, `var.list == []` may seem like it would return `true` if `var.list` were an empty list, but `[]` actually builds a value of type `tuple([])` and so the two values can never match. In this situation it's often clearer to write `length(var.list) == 0` instead. Comparison Operators[​](https://opentofu.org/docs/v1.11/language/expressions/operators/#comparison-operators "Direct link to Comparison Operators") ---------------------------------------------------------------------------------------------------------------------------------------------------- The comparison operators all expect number values and produce boolean values as results. * `a < b` returns `true` if `a` is less than `b`, or `false` otherwise. * `a <= b` returns `true` if `a` is less than or equal to `b`, or `false` otherwise. * `a > b` returns `true` if `a` is greater than `b`, or `false` otherwise. * `a >= b` returns `true` if `a` is greater than or equal to `b`, or `false` otherwise. Logical Operators[​](https://opentofu.org/docs/v1.11/language/expressions/operators/#logical-operators "Direct link to Logical Operators") ------------------------------------------------------------------------------------------------------------------------------------------- The logical operators all expect bool values and produce bool values as results. * `a || b` returns `true` if either `a` or `b` is `true`, or `false` if both are `false`. * `a && b` returns `true` if both `a` and `b` are `true`, or `false` if either one is `false`. * `!a` returns `true` if `a` is `false`, and `false` if `a` is `true`. OpenTofu does not have an operator for the "exclusive OR" operation. If you know that both operators are boolean values then exclusive OR is equivalent to the `!=` ("not equal") operator. The logical operators in OpenTofu are short-circuiting, meaning `var.foo == null || var.foo.bar == 1` will not produce an error message if `var.foo` is `null` because `var.foo.bar` is not evaluated. * [Arithmetic Operators](https://opentofu.org/docs/v1.11/language/expressions/operators/#arithmetic-operators) * [Equality Operators](https://opentofu.org/docs/v1.11/language/expressions/operators/#equality-operators) * [Comparison Operators](https://opentofu.org/docs/v1.11/language/expressions/operators/#comparison-operators) * [Logical Operators](https://opentofu.org/docs/v1.11/language/expressions/operators/#logical-operators) --- # Conditional Expressions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/expressions/conditionals/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Conditional Expressions ======================= A _conditional expression_ uses the value of a boolean expression to select one of two values. Syntax[​](https://opentofu.org/docs/v1.11/language/expressions/conditionals/#syntax "Direct link to Syntax") ------------------------------------------------------------------------------------------------------------- The syntax of a conditional expression is as follows: Code Block condition ? true_val : false_val If `condition` is `true` then the result is `true_val`. If `condition` is `false` then the result is `false_val`. A common use of conditional expressions is to define defaults to replace invalid values: Code Block var.a != "" ? var.a : "default-a" If `var.a` is an empty string then the result is `"default-a"`, but otherwise it is the actual value of `var.a`. Conditions[​](https://opentofu.org/docs/v1.11/language/expressions/conditionals/#conditions "Direct link to Conditions") ------------------------------------------------------------------------------------------------------------------------- The condition can be any expression that resolves to a boolean value. This will usually be an expression that uses the equality, comparison, or logical operators. ### Custom Condition Checks[​](https://opentofu.org/docs/v1.11/language/expressions/conditionals/#custom-condition-checks "Direct link to Custom Condition Checks") You can create conditions that produce custom error messages for several types of objects in a configuration. For example, you can add a condition to an input variable that checks whether incoming image IDs are formatted properly. Custom conditions can help capture assumptions, helping future maintainers understand the configuration design and intent. They also return useful information about errors earlier and in context, helping consumers more easily diagnose issues in their configurations. Refer to [Custom Condition Checks](https://opentofu.org/docs/v1.11/language/expressions/custom-conditions/#input-variable-validation) for details. Result Types[​](https://opentofu.org/docs/v1.11/language/expressions/conditionals/#result-types "Direct link to Result Types") ------------------------------------------------------------------------------------------------------------------------------- The two result values may be of any type, but they must both be of the _same_ type so that OpenTofu can determine what type the whole conditional expression will return without knowing the condition value. If the two result expressions don't produce the same type then OpenTofu will attempt to find a type that they can both convert to, and make those conversions automatically if so. For example, the following expression is valid and will always return a string, because in OpenTofu all numbers can convert automatically to a string using decimal digits: Code Block var.example ? 12 : "hello" Relying on this automatic conversion behavior can be confusing for those who are not familiar with OpenTofu's conversion rules though, so we recommend being explicit using type conversion functions in any situation where there may be some uncertainty about the expected result type. The following example is contrived because it would be easier to write the constant `"12"` instead of the type conversion in this case, but shows how to use [`tostring`](https://opentofu.org/docs/v1.11/language/functions/tostring/) to explicitly convert a number to a string. Code Block var.example ? tostring(12) : "hello" * [Syntax](https://opentofu.org/docs/v1.11/language/expressions/conditionals/#syntax) * [Conditions](https://opentofu.org/docs/v1.11/language/expressions/conditionals/#conditions) * [Custom Condition Checks](https://opentofu.org/docs/v1.11/language/expressions/conditionals/#custom-condition-checks) * [Result Types](https://opentofu.org/docs/v1.11/language/expressions/conditionals/#result-types) --- # Command Line Arguments | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.6/cli/cloud/command-line-arguments/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) This is documentation for OpenTofu **1.6.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://opentofu.org/docs/v1.11/) ** (1.11.x). Command Line Arguments ====================== When your configuration includes a `cloud` block, commands that make local modifications to OpenTofu state and then push them back up to the remote workspace accept the following option to modify that behavior: * `-ignore-remote-version` - Override checking that the local and remote OpenTofu versions agree, making an operation proceed even when there is a mismatch. State-modification operations usually require using a local version of the OpenTofu CLI that is compatible with the OpenTofu version selected in the remote workspace settings. This prevents the local operation from creating a new state snapshot that the workspace's remote execution environment cannot decode. We recommend against using this option unless absolutely necessary. Overriding this check can result in a cloud backend workspace that is no longer able to complete remote operations with the currently selected version of OpenTofu. --- # Using the Cloud Backend with OpenTofu CLI | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.6/cli/cloud/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) This is documentation for OpenTofu **1.6.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://opentofu.org/docs/v1.11/) ** (1.11.x). On this page Using the Cloud Backend with OpenTofu CLI ========================================= The OpenTofu CLI lets you use cloud backends on the command line. When you use the cloud backend CLI workflow, operations like `tofu plan` or `tofu apply` are remotely executed in the cloud backend's run environment by default, with log output streaming to the local terminal. This lets you use cloud backend's features within the familiar OpenTofu CLI workflow. Cloud backend services may choose to implement only a subset of the available features. Workspaces can also be configured for local execution, in which case the cloud backend only stores state. In this mode, the cloud backend behaves just like a standard state backend. Documentation Summary[​](https://opentofu.org/docs/v1.6/cli/cloud/#documentation-summary "Direct link to Documentation Summary") --------------------------------------------------------------------------------------------------------------------------------- * [Cloud Backend Settings](https://opentofu.org/docs/v1.6/cli/cloud/settings/) documents the `cloud` block that you must add to your configuration to enable cloud backend support. * [Initializing and Migrating](https://opentofu.org/docs/v1.6/cli/cloud/migrating/) describes how to start using the cloud backend with a working directory that already has state data. * [Command Line Arguments](https://opentofu.org/docs/v1.6/cli/cloud/command-line-arguments/) lists the OpenTofu command flags that are specific to using OpenTofu with the cloud backend. * [Documentation Summary](https://opentofu.org/docs/v1.6/cli/cloud/#documentation-summary) --- # Splat Expressions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/expressions/splat/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Splat Expressions ================= A _splat expression_ provides a more concise way to express a common operation that could otherwise be performed with a `for` expression. If `var.list` is a list of objects that all have an attribute `id`, then a list of the ids could be produced with the following `for` expression: Code Block [for o in var.list : o.id] This is equivalent to the following _splat expression:_ Code Block var.list[*].id The special `[*]` symbol iterates over all of the elements of the list given to its left and accesses from each one the attribute name given on its right. A splat expression can also be used to access attributes and indexes from lists of complex types by extending the sequence of operations to the right of the symbol: Code Block var.list[*].interfaces[0].name The above expression is equivalent to the following `for` expression: Code Block [for o in var.list : o.interfaces[0].name] Splat Expressions with Maps[​](https://opentofu.org/docs/v1.11/language/expressions/splat/#splat-expressions-with-maps "Direct link to Splat Expressions with Maps") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- The splat expression patterns shown above apply only to lists, sets, and tuples. To get a similar result with a map or object value you must use [`for` expressions](https://opentofu.org/docs/v1.11/language/expressions/for/) . Resources that use the `for_each` argument will appear in expressions as a map of objects, so you can't use splat expressions with those resources. For more information, see [Referring to Resource Instances](https://opentofu.org/docs/v1.11/language/meta-arguments/for_each/#referring-to-instances) . Single Values as Lists[​](https://opentofu.org/docs/v1.11/language/expressions/splat/#single-values-as-lists "Direct link to Single Values as Lists") ------------------------------------------------------------------------------------------------------------------------------------------------------ Splat expressions have a special behavior when you apply them to a value that isn't a list, set, or tuple. If the value is anything other than a null value then the splat expression will transform it into a single-element list, or more accurately a single-element tuple value. If the value is _null_ then the splat expression will return an empty tuple. This special behavior can be useful for modules that accept optional input variables whose default value is `null` to represent the absence of any value. This allows the module to adapt the variable value for OpenTofu language features designed to work with collections. For example: Code Block variable "website_setting" { type = object({ index_document = string error_document = string }) default = null}resource "aws_s3_bucket" "example" { # ... dynamic "website" { for_each = var.website_setting[*] content { index_document = website.value.index_document error_document = website.value.error_document } }} The above example uses a [`dynamic` block](https://opentofu.org/docs/v1.11/language/expressions/dynamic-blocks/) , which generates zero or more nested blocks based on a collection value. The input variable `var.website_setting` is defined as a single object that might be null, so the `dynamic` block's `for_each` expression uses `[*]` to ensure that there will be one block if the module caller sets the website argument, or zero blocks if the caller leaves it set to null. This special behavior of splat expressions is not obvious to an unfamiliar reader, so we recommend using it only in `for_each` arguments and similar situations where the context implies working with a collection. Otherwise, the meaning of the expression may be unclear to future readers. Legacy (Attribute-only) Splat Expressions[​](https://opentofu.org/docs/v1.11/language/expressions/splat/#legacy-attribute-only-splat-expressions "Direct link to Legacy (Attribute-only) Splat Expressions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Earlier versions of the OpenTofu language had a slightly different version of splat expressions, which OpenTofu continues to support for backward compatibility. This older variant is less useful than the modern form described above, and so we recommend against using it in new configurations. The legacy "attribute-only" splat expressions use the sequence `.*`, instead of `[*]`: Code Block var.list.*.interfaces[0].name This form has a subtly different behavior, equivalent to the following `for` expression: Code Block [for o in var.list : o.interfaces][0].name Notice that with the attribute-only splat expression the index operation `[0]` is applied to the result of the iteration, rather than as part of the iteration itself. Only the attribute lookups apply to each element of the input. This limitation was confusing some people using older versions of OpenTofu and so we recommend always using the new-style splat expressions, with `[*]`, to get the more consistent behavior. * [Splat Expressions with Maps](https://opentofu.org/docs/v1.11/language/expressions/splat/#splat-expressions-with-maps) * [Single Values as Lists](https://opentofu.org/docs/v1.11/language/expressions/splat/#single-values-as-lists) * [Legacy (Attribute-only) Splat Expressions](https://opentofu.org/docs/v1.11/language/expressions/splat/#legacy-attribute-only-splat-expressions) --- # Command: import | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/import/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: import =============== The `tofu import` command [imports existing resources](https://opentofu.org/docs/v1.11/cli/import/) into OpenTofu. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/import/#usage "Direct link to Usage") -------------------------------------------------------------------------------------------- Usage: `tofu import [options] ADDRESS ID` Import will find the existing resource from ID and import it into your OpenTofu state at the given ADDRESS. ADDRESS must be a valid [resource address](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/) . Because any resource address is valid, the import command can import resources into modules as well as directly into the root of your state. ID is dependent on the resource type being imported. For example, for AWS EC2 instances it is the instance ID (`i-abcd1234`) but for AWS Route53 zones it is the zone ID (`Z12ABC4UGMOZ2N`). Please reference the provider documentation for details on the ID format. If you're unsure, feel free to just try an ID. If the ID is invalid, you'll just receive an error message. Warning OpenTofu expects that each remote object it is managing will be bound to only one resource address, which is normally guaranteed by OpenTofu itself having created all objects. If you import existing objects into OpenTofu, be careful to import each remote object to only one OpenTofu resource address. If you import the same object multiple times, OpenTofu may exhibit unwanted behavior. For more information on this assumption, see [the State section](https://opentofu.org/docs/v1.11/language/state/) . Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu import`. The command-line flags are all optional. The following flags are available: * `-config=path` - Path to directory of OpenTofu configuration files that configure the provider for import. This defaults to your working directory. If this directory contains no OpenTofu configuration files, the provider must be configured via manual input or environmental variables. * `-input=true` - Whether to ask for input for provider configuration. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=0s` - Duration to retry a state lock. * `-no-color` - If specified, output won't contain any color. * `-parallelism=n` - Limit the number of concurrent operation as OpenTofu [walks the graph](https://opentofu.org/docs/v1.11/internals/graph/#walking-the-graph) . Defaults to 10. * `-provider=provider` - **Deprecated** Override the provider configuration to use when importing the object. By default, OpenTofu uses the provider specified in the configuration for the target resource, and that is the best behavior in most cases. * `-var 'foo=bar'` - Set a variable in the OpenTofu configuration. This flag can be set multiple times. Variable values are interpreted as [literal expressions](https://opentofu.org/docs/v1.11/language/expressions/types/) in the OpenTofu language, so list and map values can be specified via this flag. * `-var-file=foo` - Set variables in the OpenTofu configuration from a [variable file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . If a `terraform.tfvars` or any `.auto.tfvars` files are present in the current directory, they will be automatically loaded. `terraform.tfvars` is loaded first and the `.auto.tfvars` files after in alphabetical order. Any files specified by `-var-file` override any values set automatically from files in the working directory. This flag can be used multiple times. This is only useful with the `-config` flag. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.11/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.11/language/settings/backends/remote/) only, `tofu import` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/v1.11/cli/cloud/command-line-arguments/#ignore-remote-version) . For configurations using [the `local` backend](https://opentofu.org/docs/v1.11/language/settings/backends/local/) only, `tofu import` also accepts the legacy options [`-state`, `-state-out`, and `-backup`](https://opentofu.org/docs/v1.11/language/settings/backends/local/#command-line-arguments) . Provider Configuration[​](https://opentofu.org/docs/v1.11/cli/commands/import/#provider-configuration "Direct link to Provider Configuration") ----------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu will attempt to load configuration files that configure the provider being used for import. If no configuration files are present or no configuration for that specific provider is present, OpenTofu will prompt you for access credentials. You may also specify environmental variables to configure the provider. The only limitation OpenTofu has when reading the configuration files is that the import provider configurations must not depend on non-variable inputs. For example, a provider configuration cannot depend on a data source. As a working example, if you're importing AWS resources and you have a configuration file with the contents below, then OpenTofu will configure the AWS provider with this file. Code Block variable "access_key" {}variable "secret_key" {}provider "aws" { access_key = "${var.access_key}" secret_key = "${var.secret_key}"} Example: Import into Resource[​](https://opentofu.org/docs/v1.11/cli/commands/import/#example-import-into-resource "Direct link to Example: Import into Resource") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- This example will import an AWS instance into the `aws_instance` resource named `foo`: Code Block $ tofu import aws_instance.foo i-abcd1234 Example: Import into Module[​](https://opentofu.org/docs/v1.11/cli/commands/import/#example-import-into-module "Direct link to Example: Import into Module") ------------------------------------------------------------------------------------------------------------------------------------------------------------- The example below will import an AWS instance into the `aws_instance` resource named `bar` into a module named `foo`: Code Block $ tofu import module.foo.aws_instance.bar i-abcd1234 Example: Import into Resource configured with count[​](https://opentofu.org/docs/v1.11/cli/commands/import/#example-import-into-resource-configured-with-count "Direct link to Example: Import into Resource configured with count") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The example below will import an AWS instance into the first instance of the `aws_instance` resource named `baz` configured with [`count`](https://opentofu.org/docs/v1.11/language/meta-arguments/count/) : Code Block $ tofu import 'aws_instance.baz[0]' i-abcd1234 Example: Import into Resource configured with for\_each[​](https://opentofu.org/docs/v1.11/cli/commands/import/#example-import-into-resource-configured-with-for_each "Direct link to Example: Import into Resource configured with for_each") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The example below will import an AWS instance into the `"example"` instance of the `aws_instance` resource named `baz` configured with [`for_each`](https://opentofu.org/docs/v1.11/language/meta-arguments/for_each/) : Linux, Mac OS, and UNIX: Code Block $ tofu import 'aws_instance.baz["example"]' i-abcd1234 PowerShell: Code Block $ tofu import 'aws_instance.baz[\"example\"]' i-abcd1234 Windows `cmd.exe`: Code Block $ tofu import aws_instance.baz[\"example\"] i-abcd1234 * [Usage](https://opentofu.org/docs/v1.11/cli/commands/import/#usage) * [Provider Configuration](https://opentofu.org/docs/v1.11/cli/commands/import/#provider-configuration) * [Example: Import into Resource](https://opentofu.org/docs/v1.11/cli/commands/import/#example-import-into-resource) * [Example: Import into Module](https://opentofu.org/docs/v1.11/cli/commands/import/#example-import-into-module) * [Example: Import into Resource configured with count](https://opentofu.org/docs/v1.11/cli/commands/import/#example-import-into-resource-configured-with-count) * [Example: Import into Resource configured with for\_each](https://opentofu.org/docs/v1.11/cli/commands/import/#example-import-into-resource-configured-with-for_each) --- # Command: providers lock | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/providers/lock/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: providers lock ======================= The `tofu providers lock` consults upstream registries (by default) in order to write provider dependency information into [the dependency lock file](https://opentofu.org/docs/v1.11/language/files/dependency-lock/) . The common way to update the dependency lock file is as a side-effect of normal provider installation during [`tofu init`](https://opentofu.org/docs/v1.11/cli/commands/init/) , but there are several situations where that automatic approach may not be sufficient: * If you are running OpenTofu in an environment that uses [alternative provider installation methods](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation) , such as filesystem or network mirrors, normal provider installation will not access the origin registry for a provider and therefore OpenTofu will not be able to populate all of the possible package checksums for the selected provider versions. If you use `tofu lock` to write the official release checksums for a provider into the dependency lock file then future `tofu init` runs will verify the packages available in your selected mirror against the official checksums previously recorded, giving additional certainty that the mirror is serving the provider packages it is claiming to. * If your team runs OpenTofu across a number of different platforms (e.g. on both Windows and Linux) and the upstream registry for a provider is unable to provide signed checksums using the latest hashing scheme, subsequent runs of OpenTofu on other platforms may [add additional checksums to the lock file](https://opentofu.org/docs/v1.11/language/files/dependency-lock/#new-provider-package-checksums) . You can avoid that by pre-populating hashes for all of the platforms you intend to use, using the `tofu providers lock` command. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/providers/lock/#usage "Direct link to Usage") ---------------------------------------------------------------------------------------------------- Usage: `tofu providers lock [options] [providers...]` Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu providers lock`. This command accepts the following generic options: * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. With no additional command line arguments, `tofu providers lock` will analyze the configuration in the current working directory to find all of the providers it depends on, and it will fetch the necessary data about those providers from their origin registries and then update [the dependency lock file](https://opentofu.org/docs/v1.11/language/files/dependency-lock/) to include a selected version for each provider and all of the package checksums that are covered by the provider developer's cryptographic signature. Warning The `tofu providers lock` command prints information about what it has fetched and whether each package was signed using a cryptographic signature, but it cannot automatically verify that the providers are trustworthy and that they comply with your local system policies or relevant regulations. Review the signing key information in the output to confirm that you trust all of the signers before committing the updated lock file to your version control system. If you list one or more provider source addresses on the command line then `tofu providers lock` will restrict its work only to those providers, leaving the lock entries for other providers (if any) unchanged. You can customize the default behavior using the following additional option: * `-fs-mirror=PATH` - Direct OpenTofu to look for provider packages in the given local filesystem mirror directory, instead of in upstream registries. The given directory must use the usual filesystem mirror directory layout. * `-net-mirror=URL` - Direct OpenTofu to look for provider packages in the given network mirror service, instead of in upstream registries. The given URL must implement [the OpenTofu provider network mirror protocol](https://opentofu.org/docs/v1.11/internals/provider-network-mirror-protocol/) . * `-platform=OS_ARCH` - Specify a platform you intend to use to work with this OpenTofu configuration. OpenTofu will ensure that the providers are all available for the given platform and will save enough package checksums in the lock file to support _at least_ the specified platforms. Use this option multiple times to include checksums for multiple target systems. Target platform names consist of an operating system and a CPU architecture. For example, `linux_amd64` selects the Linux operating system running on an AMD64 or x86\_64 CPU. There is more detail on this option in the following section. Specifying Target Platforms[​](https://opentofu.org/docs/v1.11/cli/commands/providers/lock/#specifying-target-platforms "Direct link to Specifying Target Platforms") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- In your environment you may, for example, have both developers who work with your OpenTofu configuration on their Windows or macOS workstations _and_ automated systems that apply the configuration while running on Linux. In that situation, you could choose to verify that all of your providers support all of those platforms, and to pre-populate the lock file with the necessary checksums, by running `tofu providers lock` and specifying those three platforms: Code Block tofu providers lock \ -platform=windows_amd64 \ # 64-bit Windows -platform=darwin_amd64 \ # 64-bit macOS -platform=linux_amd64 # 64-bit Linux (The above example uses Unix-style shell wrapping syntax for readability. If you are running the command on Windows then you will need to put all of the arguments on a single line, and remove the backslashes and comments.) Lock Entries for In-house Providers[​](https://opentofu.org/docs/v1.11/cli/commands/providers/lock/#lock-entries-for-in-house-providers "Direct link to Lock Entries for In-house Providers") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- An _in-house provider_ is one that isn't published on a real OpenTofu provider registry because it's developed and used only within a particular organization and distributed via either a filesystem mirror or network mirror. By default, `tofu providers lock` assumes all providers are available at a OpenTofu provider registry and tries to contact the origin registries in order to get access to the most detailed information about the provider packages. To create a lock entry for a particular provider that is available only in a local mirror, you can use either the `-fs-mirror` or `-net-mirror` command line options to override the default behavior of consulting the provider's origin registry: Code Block tofu providers lock \ -fs-mirror=/usr/local/tofu/providers -platform=windows_amd64 \ -platform=darwin_amd64 \ -platform=linux_amd64 \ tf.example.com/ourcompany/ourplatform (The above example uses Unix-style shell wrapping syntax for readability. If you are running the command on Windows then you will need to put all of the arguments on a single line, and remove the backslashes.) Because the command above includes the provider source address `tf.example.com/ourcompany/ourplatform`, `tofu providers lock` will only attempt to access that particular provider and will leave the lock entries for any other providers unchanged. If you have a variety of different providers available from different sources, you can run `tofu providers lock` multiple times and specify a different subset of your providers each time. The `-fs-mirror` and `-net-mirror` options have the same meaning as `filesystem_mirror` and `network_mirror` blocks in [the provider installation methods configuration](https://opentofu.org/docs/v1.11/cli/config/config-file/#provider-installation) , but specify only a single method in order to be explicit about where you intend to derive the package checksum information from. Note that only an origin registry can provide official checksums covered by the original developer's cryptographic signature. Lock entries created from filesystem or network mirrors will therefore cover only the exact platforms you requested, and the recorded checksums will be those reported by the mirror, rather than the origin registry's official checksums. If you want to ensure that the recorded checksums are the ones signed by the original provider publisher, run this command _without_ either the `-fs-mirror` or `-net-mirror` options to fetch all information from origin registries. If you wish, you can publish your in-house providers via an in-house provider registry, which will then allow locking and installation of those providers without any special options or additional CLI configuration. For more information, see [the provider registry protocol](https://opentofu.org/docs/v1.11/internals/provider-registry-protocol/) . * [Usage](https://opentofu.org/docs/v1.11/cli/commands/providers/lock/#usage) * [Specifying Target Platforms](https://opentofu.org/docs/v1.11/cli/commands/providers/lock/#specifying-target-platforms) * [Lock Entries for In-house Providers](https://opentofu.org/docs/v1.11/cli/commands/providers/lock/#lock-entries-for-in-house-providers) --- # Command: validate | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/validate/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: validate ================= The `tofu validate` command validates the configuration files in a directory, referring only to the configuration and not accessing any remote services such as remote state, provider APIs, etc. Note Use of [variables in module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu validate`. Validate runs checks that verify whether a configuration is syntactically valid and internally consistent, regardless of existing state. It is thus primarily useful for general verification of reusable modules, including correctness of attribute names and value types. Warning Validate does not have access to the existing state, validation checks that require state access will be skipped. It is safe to run this command automatically, for example as a post-save check in a text editor or as a test step for a re-usable module in a CI system. Validation requires an initialized working directory with any referenced plugins and modules installed. To initialize a working directory for validation without accessing any configured backend, use: Code Block $ tofu init -backend=false To verify configuration in the context of a particular run (a particular target workspace, input variable values, etc), use the `tofu plan` command instead, which includes an implied validation check. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/validate/#usage "Direct link to Usage") ---------------------------------------------------------------------------------------------- Usage: `tofu validate [options]` This command accepts the following options: * `-json` - Produce output in a machine-readable JSON format, suitable for use in text editor integrations and other automated systems. Always disables color. * `-no-color` - If specified, output won't contain any color. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. JSON Output Format[​](https://opentofu.org/docs/v1.11/cli/commands/validate/#json-output-format "Direct link to JSON Output Format") ------------------------------------------------------------------------------------------------------------------------------------- When you use the `-json` option, OpenTofu will produce validation results in JSON format to allow using the validation result for tool integrations, such as highlighting errors in a text editor. As with all JSON output options, it's possible that OpenTofu will encounter an error prior to beginning the validation task that will thus not be subject to the JSON output setting. For that reason, external software consuming OpenTofu's output should be prepared to find data on stdout that _isn't_ valid JSON, which it should then treat as a generic error case. The output includes a `format_version` key, which has value `"1.0"`. The semantics of this version are: * We will increment the minor version, e.g. `"1.1"`, for backward-compatible changes or additions. Ignore any object properties with unrecognized names to remain forward-compatible with future minor versions. * We will increment the major version, e.g. `"2.0"`, for changes that are not backward-compatible. Reject any input which reports an unsupported major version. We will introduce new major versions only within the bounds of [the OpenTofu 1.0 Compatibility Promises](https://opentofu.org/docs/v1.11/language/v1-compatibility-promises/) . In the normal case, OpenTofu will print a JSON object to the standard output stream. The top-level JSON object will have the following properties: * `valid` (boolean): Summarizes the overall validation result, by indicating `true` if OpenTofu considers the current configuration to be valid or `false` if it detected any errors. * `error_count` (number): A zero or positive whole number giving the count of errors OpenTofu detected. If `valid` is `true` then `error_count` will always be zero, because it is the presence of errors that indicates that a configuration is invalid. * `warning_count` (number): A zero or positive whole number giving the count of warnings OpenTofu detected. Warnings do not cause OpenTofu to consider a configuration to be invalid, but they do indicate potential caveats that a user should consider and possibly resolve. * `diagnostics` (array of objects): A JSON array of nested objects that each describe an error or warning from OpenTofu. The nested objects in `diagnostics` have the following properties: * `severity` (string): A string keyword, either `"error"` or `"warning"`, indicating the diagnostic severity. The presence of errors causes OpenTofu to consider a configuration to be invalid, while warnings are just advice or caveats to the user which do not block working with the configuration. Later versions of OpenTofu may introduce new severity keywords, so consumers should be prepared to accept and ignore severity values they don't understand. * `summary` (string): A short description of the nature of the problem that the diagnostic is reporting. In OpenTofu's usual human-oriented diagnostic messages, the summary serves as a sort of "heading" for the diagnostic, printed after the "Error:" or "Warning:" indicator. Summaries are typically short, single sentences, but can sometimes be longer as a result of returning errors from subsystems that are not designed to return full diagnostics, where the entire error message therefore becomes the summary. In those cases, the summary might include newline characters which a renderer should honor when presenting the message visually to a user. * `detail` (string): An optional additional message giving more detail about the problem. In OpenTofu's usual human-oriented diagnostic messages, the detail provides the paragraphs of text that appear after the heading and the source location reference. Detail messages are often multiple paragraphs and possibly interspersed with non-paragraph lines, so tools which aim to present detail messages to the user should distinguish between lines without leading spaces, treating them as paragraphs, and lines with leading spaces, treating them as preformatted text. Renderers should then soft-wrap the paragraphs to fit the width of the rendering container, but leave the preformatted lines unwrapped. Some OpenTofu detail messages contain an approximation of bullet lists using ASCII characters to mark the bullets. This is not a contractural formatting convention, so renderers should avoid depending on it and should instead treat those lines as either paragraphs or preformatted text. Future versions of this format may define additional rules for other text conventions, but will maintain backward compatibility. * `range` (object): An optional object referencing a portion of the configuration source code that the diagnostic message relates to. For errors, this will typically indicate the bounds of the specific block header, attribute, or expression which was detected as invalid. A source range is an object with a property `filename` which gives the filename as a relative path from the current working directory, and then two properties `start` and `end` which are both themselves objects describing source positions, as described below. Not all diagnostic messages are connected with specific portions of the configuration, so `range` will be omitted or `null` for diagnostic messages where it isn't relevant. * `snippet` (object): An optional object including an excerpt of the configuration source code that the diagnostic message relates to. The snippet information includes: * `context` (string): An optional summary of the root context of the diagnostic. For example, this might be the resource block containing the expression which triggered the diagnostic. For some diagnostics this information is not available, and then this property will be `null`. * `code` (string): A snippet of OpenTofu configuration including the source of the diagnostic. This can be multiple lines and may include additional configuration source code around the expression which triggered the diagnostic. * `start_line` (number): A one-based line count representing the position in the source file at which the `code` excerpt begins. This is not necessarily the same value as `range.start.line`, as it is possible for `code` to include one or more lines of context before the source of the diagnostic. * `highlight_start_offset` (number): A zero-based character offset into the `code` string, pointing at the start of the expression which triggered the diagnostic. * `highlight_end_offset` (number): A zero-based character offset into the `code` string, pointing at the end of the expression which triggered the diagnostic. * `values` (array of objects): Contains zero or more expression values which may be useful in understanding the source of a diagnostic in a complex expression. These expression value objects are described below. ### Source Position[​](https://opentofu.org/docs/v1.11/cli/commands/validate/#source-position "Direct link to Source Position") A source position object, as used in the `range` property of a diagnostic object, has the following properties: * `byte` (number): A zero-based byte offset into the indicated file. * `line` (number): A one-based line count for the line containing the relevant position in the indicated file. * `column` (number): A one-based count of _Unicode characters_ from the start of the line indicated in `line`. A `start` position is inclusive while an `end` position is exclusive. The exact positions used for particular error messages are intended for human interpretation only. ### Expression Value[​](https://opentofu.org/docs/v1.11/cli/commands/validate/#expression-value "Direct link to Expression Value") An expression value object gives additional information about a value which is part of the expression which triggered the diagnostic. This is especially useful when using `for_each` or similar constructs, in order to identify exactly which values are responsible for an error. The object has two properties: * `traversal` (string): An HCL-like traversal string, such as `var.instance_count`. Complex index key values may be elided, so this will not always be valid, parseable HCL. The contents of this string are intended to be human-readable. * `statement` (string): A short English-language fragment describing the value of the expression when the diagnostic was triggered. The contents of this string are intended to be human-readable and are subject to change in future versions of OpenTofu. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/validate/#usage) * [JSON Output Format](https://opentofu.org/docs/v1.11/cli/commands/validate/#json-output-format) * [Source Position](https://opentofu.org/docs/v1.11/cli/commands/validate/#source-position) * [Expression Value](https://opentofu.org/docs/v1.11/cli/commands/validate/#expression-value) --- # Types and Values | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/expressions/types/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Types and Values ================ The result of an expression is a _value_. All values have a _type_, which dictates where that value can be used and what transformations can be applied to it. Types[​](https://opentofu.org/docs/v1.11/language/expressions/types/#types "Direct link to Types") --------------------------------------------------------------------------------------------------- The OpenTofu language uses the following types for its values: * `string`: a sequence of Unicode characters representing some text, like `"hello"`. * `number`: a numeric value. The `number` type can represent both whole numbers like `15` and fractional values like `6.283185`. * `bool`: a boolean value, either `true` or `false`. `bool` values can be used in conditional logic. * `list`: a sequence of values, like `["us-west-1a", "us-west-1c"]`. Elements in a list are identified by consecutive whole numbers, starting with zero. * `set`: a collection of unique values that do not have any secondary identifiers or ordering. * `map`: a group of values identified by named labels, like `{name = "Mabel", age = 52}`. Strings, numbers, and bools are sometimes called _primitive types._ Lists and sets are forms of tuples. Maps are a form of objects. Tuples and maps are sometimes called _complex types,_ _structural types,_ or _collection types._ See [Type Constraints](https://opentofu.org/docs/v1.11/language/expressions/type-constraints/) for a more detailed description of complex types. Finally, there is one special value that has _no_ type: * `null`: a value that represents _absence_ or _omission._ If you set an argument of a resource to `null`, OpenTofu behaves as though you had completely omitted it β€”Β it will use the argument's default value if it has one, or raise an error if the argument is mandatory. `null` is most useful in conditional expressions, so you can dynamically omit an argument if a condition isn't met. Literal Expressions[​](https://opentofu.org/docs/v1.11/language/expressions/types/#literal-expressions "Direct link to Literal Expressions") --------------------------------------------------------------------------------------------------------------------------------------------- A _literal expression_ is an expression that directly represents a particular constant value. OpenTofu has a literal expression syntax for each of the value types described above. ### Strings[​](https://opentofu.org/docs/v1.11/language/expressions/types/#strings "Direct link to Strings") Strings are usually represented by a double-quoted sequence of Unicode characters, `"like this"`. There is also a "heredoc" syntax for more complex strings. String literals are the most complex kind of literal expression in OpenTofu, and have their own page of documentation. See [Strings](https://opentofu.org/docs/v1.11/language/expressions/strings/) for information about escape sequences, the heredoc syntax, interpolation, and template directives. ### Numbers[​](https://opentofu.org/docs/v1.11/language/expressions/types/#numbers "Direct link to Numbers") Numbers are represented by unquoted sequences of digits with or without a decimal point, like `15` or `6.283185`. ### Bools[​](https://opentofu.org/docs/v1.11/language/expressions/types/#bools "Direct link to Bools") Bools are represented by the unquoted symbols `true` and `false`. ### Null[​](https://opentofu.org/docs/v1.11/language/expressions/types/#null "Direct link to Null") The null value is represented by the unquoted symbol `null`. ### Lists/Tuples[​](https://opentofu.org/docs/v1.11/language/expressions/types/#liststuples "Direct link to Lists/Tuples") Lists/tuples are represented by a pair of square brackets containing a comma-separated sequence of values, like `["a", 15, true]`. List literals can be split into multiple lines for readability, but always require a comma between values. A comma after the final value is allowed, but not required. Values in a list can be arbitrary expressions. ### Maps/Objects[​](https://opentofu.org/docs/v1.11/language/expressions/types/#mapsobjects "Direct link to Maps/Objects") Maps/objects are represented by a pair of curly braces containing a series of ` = ` pairs: Code Block { name = "John" age = 52} Key/value pairs can be separated by either a comma or a line break. The values in a map can be arbitrary expressions. The keys in a map must be strings; they can be left unquoted if they are a valid [identifier](https://opentofu.org/docs/v1.11/language/syntax/configuration/#identifiers) , but must be quoted otherwise. You can use a non-literal string expression as a key by wrapping it in parentheses, like `(var.business_unit_tag_name) = "SRE"`. Indices and Attributes[​](https://opentofu.org/docs/v1.11/language/expressions/types/#indices-and-attributes "Direct link to Indices and Attributes") ------------------------------------------------------------------------------------------------------------------------------------------------------ Elements of list/tuple and map/object values can be accessed using the square-bracket index notation, like `local.list[3]`. The expression within the brackets must be a whole number for list and tuple values or a string for map and object values. Map/object attributes with names that are valid identifiers can also be accessed using the dot-separated attribute notation, like `local.object.attrname`. In cases where a map might contain arbitrary user-specified keys, we recommend using only the square-bracket index notation (`local.map["keyname"]`). More About Complex Types[​](https://opentofu.org/docs/v1.11/language/expressions/types/#more-about-complex-types "Direct link to More About Complex Types") ------------------------------------------------------------------------------------------------------------------------------------------------------------ In most situations, lists and tuples behave identically, as do maps and objects. Whenever the distinction isn't relevant, the OpenTofu documentation uses each pair of terms interchangeably (with a historical preference for "list" and "map"). However, module authors and provider developers should understand the differences between these similar types (and the related `set` type), since they offer different ways to restrict the allowed values for input variables and resource arguments. For complete details about these types (and an explanation of why the difference usually doesn't matter), see [Type Constraints](https://opentofu.org/docs/v1.11/language/expressions/type-constraints/) . Type Conversion[​](https://opentofu.org/docs/v1.11/language/expressions/types/#type-conversion "Direct link to Type Conversion") --------------------------------------------------------------------------------------------------------------------------------- Expressions are most often used to set values for the arguments of resources and child modules. In these cases, the argument has an expected type and the given expression must produce a value of that type. Where possible, OpenTofu automatically converts values from one type to another in order to produce the expected type. If this isn't possible, OpenTofu will produce a type mismatch error and you must update the configuration with a more suitable expression. OpenTofu automatically converts number and bool values to strings when needed. It also converts strings to numbers or bools, as long as the string contains a valid representation of a number or bool value. * `true` converts to `"true"`, and vice-versa * `false` converts to `"false"`, and vice-versa * `15` converts to `"15"`, and vice-versa * [Types](https://opentofu.org/docs/v1.11/language/expressions/types/#types) * [Literal Expressions](https://opentofu.org/docs/v1.11/language/expressions/types/#literal-expressions) * [Strings](https://opentofu.org/docs/v1.11/language/expressions/types/#strings) * [Numbers](https://opentofu.org/docs/v1.11/language/expressions/types/#numbers) * [Bools](https://opentofu.org/docs/v1.11/language/expressions/types/#bools) * [Null](https://opentofu.org/docs/v1.11/language/expressions/types/#null) * [Lists/Tuples](https://opentofu.org/docs/v1.11/language/expressions/types/#liststuples) * [Maps/Objects](https://opentofu.org/docs/v1.11/language/expressions/types/#mapsobjects) * [Indices and Attributes](https://opentofu.org/docs/v1.11/language/expressions/types/#indices-and-attributes) * [More About Complex Types](https://opentofu.org/docs/v1.11/language/expressions/types/#more-about-complex-types) * [Type Conversion](https://opentofu.org/docs/v1.11/language/expressions/types/#type-conversion) --- # Command: state show | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/state/show/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state show =================== The `tofu state show` command is used to show the attributes of a single resource in the [OpenTofu state](https://opentofu.org/docs/v1.11/language/state/) . Usage[​](https://opentofu.org/docs/v1.11/cli/commands/state/show/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------ Usage: `tofu state show [options] ADDRESS` The command will show the attributes of a single resource in the state file that matches the given address. This command requires an address that points to a single resource in the state. Addresses are in [resource addressing format](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/) . Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu show`. The command-line flags are all optional. The following flags are available: * `-state=path` - Path to the state file. Defaults to "terraform.tfstate". Ignored when [remote state](https://opentofu.org/docs/v1.11/language/state/remote/) is used. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. * `-show-sensitive` - If specified, sensitive values will be displayed. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. The output of `tofu state show` is intended for human consumption, not programmatic consumption. To extract state data for use in other software, use [`tofu show -json`](https://opentofu.org/docs/v1.11/cli/commands/show/#json-output) and decode the result using the documented structure. Example: Show a Resource[​](https://opentofu.org/docs/v1.11/cli/commands/state/show/#example-show-a-resource "Direct link to Example: Show a Resource") -------------------------------------------------------------------------------------------------------------------------------------------------------- The example below shows a `packet_device` resource named `worker`: Code Block $ tofu state show 'packet_device.worker'# packet_device.worker:resource "packet_device" "worker" { billing_cycle = "hourly" created = "2015-12-17T00:06:56Z" facility = "ewr1" hostname = "prod-xyz01" id = "6015bg2b-b8c4-4925-aad2-f0671d5d3b13" locked = false} Example: Show a Module Resource[​](https://opentofu.org/docs/v1.11/cli/commands/state/show/#example-show-a-module-resource "Direct link to Example: Show a Module Resource") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The example below shows a `packet_device` resource named `worker` inside a module named `foo`: Code Block $ tofu state show 'module.foo.packet_device.worker' Example: Show a Resource configured with count[​](https://opentofu.org/docs/v1.11/cli/commands/state/show/#example-show-a-resource-configured-with-count "Direct link to Example: Show a Resource configured with count") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The example below shows the first instance of a `packet_device` resource named `worker` configured with [`count`](https://opentofu.org/docs/v1.11/language/meta-arguments/count/) : Code Block $ tofu state show 'packet_device.worker[0]' Example: Show a Resource configured with for\_each[​](https://opentofu.org/docs/v1.11/cli/commands/state/show/#example-show-a-resource-configured-with-for_each "Direct link to Example: Show a Resource configured with for_each") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ The following example shows the `"example"` instance of a `packet_device` resource named `worker` configured with the [`for_each`](https://opentofu.org/docs/v1.11/language/meta-arguments/for_each/) meta-argument. You must place the resource name in single quotes when it contains special characters like double quotes. Linux, Mac OS, and UNIX: Code Block $ tofu state show 'packet_device.worker["example"]' PowerShell: Code Block $ tofu state show 'packet_device.worker[\"example\"]' Windows `cmd.exe`: Code Block $ tofu state show packet_device.worker[\"example\"] * [Usage](https://opentofu.org/docs/v1.11/cli/commands/state/show/#usage) * [Example: Show a Resource](https://opentofu.org/docs/v1.11/cli/commands/state/show/#example-show-a-resource) * [Example: Show a Module Resource](https://opentofu.org/docs/v1.11/cli/commands/state/show/#example-show-a-module-resource) * [Example: Show a Resource configured with count](https://opentofu.org/docs/v1.11/cli/commands/state/show/#example-show-a-resource-configured-with-count) * [Example: Show a Resource configured with for\_each](https://opentofu.org/docs/v1.11/cli/commands/state/show/#example-show-a-resource-configured-with-for_each) --- # Command: state replace-provider | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/state/replace-provider/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state replace-provider =============================== The `tofu state replace-provider` command is used to replace the provider for resources in a [OpenTofu state](https://opentofu.org/docs/v1.11/language/state/) . Usage[​](https://opentofu.org/docs/v1.11/cli/commands/state/replace-provider/#usage "Direct link to Usage") ------------------------------------------------------------------------------------------------------------ Usage: `tofu state replace-provider [options] FROM_PROVIDER_FQN TO_PROVIDER_FQN` This command will update all resources using the "from" provider, setting the provider to the specified "to" provider. This allows changing the source of a provider which currently has resources in state. This command will output a backup copy of the state prior to saving any changes. The backup cannot be disabled. Due to the destructive nature of this command, backups are required. Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu state replace-providers`. This command also accepts the following options: * `-auto-approve` - Skip interactive approval. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=0s` - Duration to retry a state lock. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.11/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.11/language/settings/backends/remote/) only, `tofu state replace-provider` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/v1.11/cli/cloud/command-line-arguments/#ignore-remote-version) . For configurations using [the `local` state](https://opentofu.org/docs/v1.11/language/settings/backends/local/) only, `tofu state replace-provider` also accepts the legacy options [`-state`, `-state-out`, and `-backup`](https://opentofu.org/docs/v1.11/language/settings/backends/local/#command-line-arguments) . Example[​](https://opentofu.org/docs/v1.11/cli/commands/state/replace-provider/#example "Direct link to Example") ------------------------------------------------------------------------------------------------------------------ The example below replaces the `hashicorp/aws` provider with a fork by `acme`, hosted at a private registry at `registry.acme.corp`: Code Block $ tofu state replace-provider hashicorp/aws registry.acme.corp/acme/aws * [Usage](https://opentofu.org/docs/v1.11/cli/commands/state/replace-provider/#usage) * [Example](https://opentofu.org/docs/v1.11/cli/commands/state/replace-provider/#example) --- # Writing and Modifying OpenTofu Code | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.6/cli/code/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) This is documentation for OpenTofu **1.6.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://opentofu.org/docs/v1.11/) ** (1.11.x). Writing and Modifying OpenTofu Code =================================== The [OpenTofu language](https://opentofu.org/docs/v1.6/language/) is OpenTofu's primary user interface, and all of OpenTofu's workflows rely on configurations written in the OpenTofu language. OpenTofu CLI includes several commands to make OpenTofu code more convenient to work with. Integrating these commands into your editing workflow can potentially save you time and effort. * [The `tofu console` command](https://opentofu.org/docs/v1.6/cli/commands/console/) starts an interactive shell for evaluating OpenTofu [expressions](https://opentofu.org/docs/v1.6/language/expressions/) , which can be a faster way to verify that a particular resource argument results in the value you expect. * [The `tofu fmt` command](https://opentofu.org/docs/v1.6/cli/commands/fmt/) rewrites OpenTofu configuration files to a canonical format and style, so you don't have to waste time making minor adjustments for readability and consistency. It works well as a pre-commit hook in your version control system. * [The `tofu validate` command](https://opentofu.org/docs/v1.6/cli/commands/validate/) validates the syntax and arguments of the OpenTofu configuration files in a directory, including argument and attribute names and types for resources and modules. The `plan` and `apply` commands automatically validate a configuration before performing any other work, so `validate` isn't a crucial part of the core workflow, but it can be very useful as a pre-commit hook or as part of a continuous integration pipeline. --- # Migrating to OpenTofu 1.7.x from Terraform | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.6/intro/migration/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) This is documentation for OpenTofu **1.6.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://opentofu.org/docs/v1.11/) ** (1.11.x). Migrating to OpenTofu 1.7.x from Terraform ========================================== Please select the Terraform version you are migrating from: [Terraform 1.6](https://opentofu.org/docs/v1.6/intro/migration/terraform-1.6/) ------------------------------------------------------------------------------- [Terraform 1.5 or lower](https://opentofu.org/docs/v1.6/intro/migration/terraform-1.5-or-lower/) ------------------------------------------------------------------------------------------------- --- # Use Cases | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.6/intro/use-cases/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) This is documentation for OpenTofu **1.6.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://opentofu.org/docs/v1.11/) ** (1.11.x). On this page Use Cases ========= [OpenTofu](https://opentofu.org/docs/v1.6/) is an infrastructure as code tool that lets you define infrastructure resources in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to safely and efficiently provision and manage your infrastructure throughout its lifecycle. This page describes popular OpenTofu use cases and provides related resources that you can use to create OpenTofu configurations and workflows. Multi-Cloud Deployment[​](https://opentofu.org/docs/v1.6/intro/use-cases/#multi-cloud-deployment "Direct link to Multi-Cloud Deployment") ------------------------------------------------------------------------------------------------------------------------------------------ Provisioning infrastructure across multiple clouds increases fault-tolerance, allowing for more graceful recovery from cloud provider outages. However, multi-cloud deployments add complexity because each provider has its own interfaces, tools, and workflows. OpenTofu lets you use the same workflow to manage multiple providers and handle cross-cloud dependencies. This simplifies management and orchestration for large-scale, multi-cloud infrastructures. ### Resources[​](https://opentofu.org/docs/v1.6/intro/use-cases/#resources "Direct link to Resources") * Browse the [Public OpenTofu Registry](https://github.com/opentofu/registry/tree/main/providers) to find thousands of publicly available providers. Application Infrastructure Deployment, Scaling, and Monitoring Tools[​](https://opentofu.org/docs/v1.6/intro/use-cases/#application-infrastructure-deployment-scaling-and-monitoring-tools "Direct link to Application Infrastructure Deployment, Scaling, and Monitoring Tools") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can use OpenTofu to efficiently deploy, release, scale, and monitor infrastructure for multi-tier applications. N-tier application architecture lets you scale application components independently and provides a separation of concerns. An application could consist of a pool of web servers that use a database tier, with additional tiers for API servers, caching servers, and routing meshes. OpenTofu allows you to manage the resources in each tier together, and automatically handles dependencies between tiers. For example, OpenTofu will deploy a database tier before provisioning the web servers that depend on it. Self-Service Clusters[​](https://opentofu.org/docs/v1.6/intro/use-cases/#self-service-clusters "Direct link to Self-Service Clusters") --------------------------------------------------------------------------------------------------------------------------------------- At a large organization, your centralized operations team may get many repetitive infrastructure requests. You can use OpenTofu to build a "self-serve" infrastructure model that lets product teams manage their own infrastructure independently. You can create and use OpenTofu modules that codify the standards for deploying and managing services in your organization, allowing teams to efficiently deploy services in compliance with your organization’s practices. A cloud backend can also integrate with ticketing systems like ServiceNow to automatically generate new infrastructure requests. Policy Compliance and Management[​](https://opentofu.org/docs/v1.6/intro/use-cases/#policy-compliance-and-management "Direct link to Policy Compliance and Management") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ OpenTofu can help you enforce policies on the types of resources teams can provision and use. Ticket-based review processes are a bottleneck that can slow down development. Instead, you can use Sentinel, a policy-as-code framework, to automatically enforce compliance and governance policies before OpenTofu makes infrastructure changes. Sentinel policies are available in cloud backends. PaaS Application Setup[​](https://opentofu.org/docs/v1.6/intro/use-cases/#paas-application-setup "Direct link to PaaS Application Setup") ------------------------------------------------------------------------------------------------------------------------------------------ Platform as a Service (PaaS) vendors like Heroku allow you to create web applications and attach add-ons, such as databases or email providers. Heroku can elastically scale the number of dynos or workers, but most non-trivial applications need many add-ons and external services. You can use OpenTofu to codify the setup required for a Heroku application, configure a DNSimple to set a CNAME, and set up Cloudflare as a Content Delivery Network (CDN) for the app. OpenTofu can quickly and consistently do all of this without a web interface. Software Defined Networking[​](https://opentofu.org/docs/v1.6/intro/use-cases/#software-defined-networking "Direct link to Software Defined Networking") --------------------------------------------------------------------------------------------------------------------------------------------------------- OpenTofu can interact with Software Defined Networks (SDNs) to automatically configure the network according to the needs of the applications running in it. This lets you move from a ticket-based workflow to an automated one, reducing deployment times. Kubernetes[​](https://opentofu.org/docs/v1.6/intro/use-cases/#kubernetes "Direct link to Kubernetes") ------------------------------------------------------------------------------------------------------ Kubernetes is an open-source workload scheduler for containerized applications. OpenTofu lets you both deploy a Kubernetes cluster and manage its resources (e.g., pods, deployments, services, etc.). Parallel Environments[​](https://opentofu.org/docs/v1.6/intro/use-cases/#parallel-environments "Direct link to Parallel Environments") --------------------------------------------------------------------------------------------------------------------------------------- You may have staging or QA environments that you use to test new applications before releasing them in production. As the production environment grows larger and more complex, it can be increasingly difficult to maintain an up-to-date environment for each stage of the development process. OpenTofu lets you rapidly spin up and decommission infrastructure for development, test, QA, and production. Using OpenTofu to create disposable environments as needed is more cost-efficient than maintaining each one indefinitely. Software Demos[​](https://opentofu.org/docs/v1.6/intro/use-cases/#software-demos "Direct link to Software Demos") ------------------------------------------------------------------------------------------------------------------ You can use OpenTofu to create, provision, and bootstrap a demo on various cloud providers. This lets end users easily try the software on their own infrastructure and even enables them to adjust parameters like cluster size to more rigorously test tools at any scale. * [Multi-Cloud Deployment](https://opentofu.org/docs/v1.6/intro/use-cases/#multi-cloud-deployment) * [Resources](https://opentofu.org/docs/v1.6/intro/use-cases/#resources) * [Application Infrastructure Deployment, Scaling, and Monitoring Tools](https://opentofu.org/docs/v1.6/intro/use-cases/#application-infrastructure-deployment-scaling-and-monitoring-tools) * [Self-Service Clusters](https://opentofu.org/docs/v1.6/intro/use-cases/#self-service-clusters) * [Policy Compliance and Management](https://opentofu.org/docs/v1.6/intro/use-cases/#policy-compliance-and-management) * [PaaS Application Setup](https://opentofu.org/docs/v1.6/intro/use-cases/#paas-application-setup) * [Software Defined Networking](https://opentofu.org/docs/v1.6/intro/use-cases/#software-defined-networking) * [Kubernetes](https://opentofu.org/docs/v1.6/intro/use-cases/#kubernetes) * [Parallel Environments](https://opentofu.org/docs/v1.6/intro/use-cases/#parallel-environments) * [Software Demos](https://opentofu.org/docs/v1.6/intro/use-cases/#software-demos) --- # Getting started | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.6/intro/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) This is documentation for OpenTofu **1.6.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://opentofu.org/docs/v1.11/) ** (1.11.x). On this page What is OpenTofu? ================= OpenTofu is an infrastructure as code tool that lets you define both cloud and on-prem resources in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to provision and manage all of your infrastructure throughout its lifecycle. OpenTofu can manage low-level components like compute, storage, and networking resources, as well as high-level components like DNS entries and SaaS features. How does OpenTofu work?[​](https://opentofu.org/docs/v1.6/intro/#how-does-opentofu-work "Direct link to How does OpenTofu work?") ---------------------------------------------------------------------------------------------------------------------------------- OpenTofu creates and manages resources on cloud platforms and other services through their application programming interfaces (APIs). Providers enable OpenTofu to work with virtually any platform or service with an accessible API. The OpenTofu community have already written **thousands of providers** to manage many different types of resources and services. You can find all publicly available providers on the [Public OpenTofu Registry](https://github.com/opentofu/registry/tree/main/providers) , including Amazon Web Services (AWS), Azure, Google Cloud Platform (GCP), Kubernetes, Helm, GitHub, Splunk, DataDog, and many more. The core OpenTofu workflow consists of three stages: * **Write:** You define resources, which may be across multiple cloud providers and services. For example, you might create a configuration to deploy an application on virtual machines in a Virtual Private Cloud (VPC) network with security groups and a load balancer. * **Plan:** OpenTofu creates an execution plan describing the infrastructure it will create, update, or destroy based on the existing infrastructure and your configuration. * **Apply:** On approval, OpenTofu performs the proposed operations in the correct order, respecting any resource dependencies. For example, if you update the properties of a VPC and change the number of virtual machines in that VPC, OpenTofu will recreate the VPC before scaling the virtual machines. Why OpenTofu?[​](https://opentofu.org/docs/v1.6/intro/#why-opentofu "Direct link to Why OpenTofu?") ---------------------------------------------------------------------------------------------------- ### Manage any infrastructure[​](https://opentofu.org/docs/v1.6/intro/#manage-any-infrastructure "Direct link to Manage any infrastructure") Find providers for many of the platforms and services you already use in the [Public OpenTofu Registry](https://registry.opentofu.org/) . You can also use the [Terraform Plugin SDK](https://developer.hashicorp.com/terraform/plugin) to write your own. OpenTofu takes an [immutable approach to infrastructure](https://www.hashicorp.com/resources/what-is-mutable-vs-immutable-infrastructure) , reducing the complexity of upgrading or modifying your services and infrastructure. ### Track your infrastructure[​](https://opentofu.org/docs/v1.6/intro/#track-your-infrastructure "Direct link to Track your infrastructure") OpenTofu generates a plan and prompts you for your approval before modifying your infrastructure. It also keeps track of your real infrastructure in a [state file](https://opentofu.org/docs/v1.6/language/state/) , which acts as a source of truth for your environment. OpenTofu uses the state file to determine the changes to make to your infrastructure so that it will match your configuration. ### Automate changes[​](https://opentofu.org/docs/v1.6/intro/#automate-changes "Direct link to Automate changes") OpenTofu configuration files are declarative, meaning that they describe the end state of your infrastructure. You do not need to write step-by-step instructions to create resources because OpenTofu handles the underlying logic. OpenTofu builds a resource graph to determine resource dependencies and creates or modifies non-dependent resources in parallel. This allows OpenTofu to provision resources efficiently. ### Standardize configurations[​](https://opentofu.org/docs/v1.6/intro/#standardize-configurations "Direct link to Standardize configurations") OpenTofu supports reusable configuration components called [modules](https://opentofu.org/docs/v1.6/language/modules/) that define configurable collections of infrastructure, saving time and encouraging best practices. You can use publicly available modules from the OpenTofu Registry, or write your own. ### Collaborate[​](https://opentofu.org/docs/v1.6/intro/#collaborate "Direct link to Collaborate") Since your configuration is written in a file, you can commit it to a Version Control System (VCS) and use a cloud backend to efficiently manage OpenTofu workflows across teams. A cloud backend runs OpenTofu in a consistent, reliable environment and provides secure access to shared state and secret data, role-based access controls, a private registry for sharing both modules and providers, and more. Tip Learn more about [OpenTofu use cases](https://opentofu.org/docs/v1.6/intro/use-cases/) and [how OpenTofu compares to alternatives](https://opentofu.org/docs/v1.6/intro/vs/) . Community[​](https://opentofu.org/docs/v1.6/intro/#community "Direct link to Community") ----------------------------------------------------------------------------------------- We welcome questions, suggestions, and contributions from the community. * Ask questions in [OpenTofu Discuss](https://github.com/orgs/opentofu/discussions) . * Read our [contributing guide](https://github.com/opentofu/opentofu/blob/main/CONTRIBUTING.md) . * [Submit an issue](https://github.com/opentofu/opentofu/issues) for bugs and feature requests. * [How does OpenTofu work?](https://opentofu.org/docs/v1.6/intro/#how-does-opentofu-work) * [Why OpenTofu?](https://opentofu.org/docs/v1.6/intro/#why-opentofu) * [Manage any infrastructure](https://opentofu.org/docs/v1.6/intro/#manage-any-infrastructure) * [Track your infrastructure](https://opentofu.org/docs/v1.6/intro/#track-your-infrastructure) * [Automate changes](https://opentofu.org/docs/v1.6/intro/#automate-changes) * [Standardize configurations](https://opentofu.org/docs/v1.6/intro/#standardize-configurations) * [Collaborate](https://opentofu.org/docs/v1.6/intro/#collaborate) * [Community](https://opentofu.org/docs/v1.6/intro/#community) --- # Command: state rm | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state rm ================= The main function of [OpenTofu state](https://opentofu.org/docs/v1.11/language/state/) is to track the bindings between resource instance addresses in your configuration and the remote objects they represent. Normally OpenTofu automatically updates the state in response to actions taken when applying a plan, such as removing a binding for a remote object that has now been deleted. You can use `tofu state rm` in the less common situation where you wish to remove a binding to an existing remote object without first destroying it, which will effectively make OpenTofu "forget" the object while it continues to exist in the remote system. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#usage "Direct link to Usage") ---------------------------------------------------------------------------------------------- Usage: `tofu state rm [options] ADDRESS...` OpenTofu will search the state for any instances matching the given [resource address](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/) , and remove the record of each one so that OpenTofu will no longer be tracking the corresponding remote objects. This means that although the objects will still continue to exist in the remote system, a subsequent [`tofu plan`](https://opentofu.org/docs/v1.11/cli/commands/plan/) will include an action to create a new object for each of the "forgotten" instances. Depending on the constraints imposed by the remote system, creating those objects might fail if their names or other identifiers conflict with the old objects still present. Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu state rm`. This command also accepts the following options: * `-dry-run` - Report all of the resource instances that match the given address without actually "forgetting" any of them. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.11/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.11/language/settings/backends/remote/) only, `tofu state rm` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/v1.11/cli/cloud/command-line-arguments/#ignore-remote-version) . For configurations using [the `local` state rm](https://opentofu.org/docs/v1.11/language/settings/backends/local/) only, `tofu state rm` also accepts the legacy options [`-state`, `-state-out`, and `-backup`](https://opentofu.org/docs/v1.11/language/settings/backends/local/#command-line-arguments) . Example: Remove all Instances of a Resource[​](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#example-remove-all-instances-of-a-resource "Direct link to Example: Remove all Instances of a Resource") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The following example will cause OpenTofu to "forget" all of the instances of the `packet_device` resource named "worker". Code Block $ tofu state rm 'packet_device.worker' A resource that doesn't use `count` or `for_each` has only one instance, so this is also the appropriate syntax to select that single instance. Example: Remove all Instances of a Resource in a Module[​](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#example-remove-all-instances-of-a-resource-in-a-module "Direct link to Example: Remove all Instances of a Resource in a Module") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To select a resource that you've defined in a child module you must specify the path of that module as part of the resource address: Code Block $ tofu state rm 'module.foo.packet_device.worker' Example: Remove all Instances of all Resources in a Module[​](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#example-remove-all-instances-of-all-resources-in-a-module "Direct link to Example: Remove all Instances of all Resources in a Module") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ The following example will cause OpenTofu to "forget" all of the instances associated with all resources defined in all instances of the module named `foo`: Code Block $ tofu state rm 'module.foo' Example: Remove a Particular Instance of a Resource using `count`[​](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#example-remove-a-particular-instance-of-a-resource-using-count "Direct link to example-remove-a-particular-instance-of-a-resource-using-count") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A resource defined with [the `count` meta-argument](https://opentofu.org/docs/v1.11/language/meta-arguments/count/) has multiple instances that are each identified by an integer. You can select a particular instance by including an explicit index in your given address: Code Block $ tofu state rm 'packet_device.worker[0]' Brackets (`[`, `]`) have a special meaning in some shells, so you may need to quote or escape the address in order to pass it literally to OpenTofu. The above shows the typical quoting syntax for Unix-style shells. Example: Remove a Particular Instance of a Resource using `for_each`[​](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#example-remove-a-particular-instance-of-a-resource-using-for_each "Direct link to example-remove-a-particular-instance-of-a-resource-using-for_each") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A resource defined with [the `for_each` meta-argument](https://opentofu.org/docs/v1.11/language/meta-arguments/for_each/) has multiple instances that are each identified by an string. You can select a particular instance by including an explicit key in your given address. However, the syntax for strings includes quotes and the quote symbol often has special meaning in command shells, so you'll need to use the appropriate quoting and/or escaping syntax for the shell you are using. For example: Unix-style shells, such as on Linux or macOS: Code Block $ tofu state rm 'packet_device.worker["example"]' Windows Command Prompt (`cmd.exe`): Code Block $ tofu state rm packet_device.worker[\"example\"] PowerShell: Code Block $ tofu state rm 'packet_device.worker[\"example\"]' * [Usage](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#usage) * [Example: Remove all Instances of a Resource](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#example-remove-all-instances-of-a-resource) * [Example: Remove all Instances of a Resource in a Module](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#example-remove-all-instances-of-a-resource-in-a-module) * [Example: Remove all Instances of all Resources in a Module](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#example-remove-all-instances-of-all-resources-in-a-module) * [Example: Remove a Particular Instance of a Resource using `count`](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#example-remove-a-particular-instance-of-a-resource-using-count) * [Example: Remove a Particular Instance of a Resource using `for_each`](https://opentofu.org/docs/v1.11/cli/commands/state/rm/#example-remove-a-particular-instance-of-a-resource-using-for_each) --- # Function Calls | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/expressions/function-calls/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Function Calls ============== The OpenTofu language has a number of [built-in functions](https://opentofu.org/docs/v1.11/language/functions/) that can be used in expressions to transform and combine values. These are similar to the operators but all follow a common syntax: Code Block (, ) The function name specifies which function to call. Each defined function expects a specific number of arguments with specific value types, and returns a specific value type as a result. Some functions take an arbitrary number of arguments. For example, the `min` function takes any amount of number arguments and returns the one that is numerically smallest: Code Block min(55, 3453, 2) A function call expression evaluates to the function's return value. Available Functions[​](https://opentofu.org/docs/v1.11/language/expressions/function-calls/#available-functions "Direct link to Available Functions") ------------------------------------------------------------------------------------------------------------------------------------------------------ For a full list of available functions, see [the function reference](https://opentofu.org/docs/v1.11/language/functions/) . Expanding Function Arguments[​](https://opentofu.org/docs/v1.11/language/expressions/function-calls/#expanding-function-arguments "Direct link to Expanding Function Arguments") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If the arguments to pass to a function are available in a list or tuple value, that value can be _expanded_ into separate arguments. Provide the list value as an argument and follow it with the `...` symbol: Code Block min([55, 2453, 2]...) The expansion symbol is three periods (`...`), not a Unicode ellipsis character (`…`). Expansion is a special syntax that is only available in function calls. Using Sensitive Data as Function Arguments[​](https://opentofu.org/docs/v1.11/language/expressions/function-calls/#using-sensitive-data-as-function-arguments "Direct link to Using Sensitive Data as Function Arguments") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When using sensitive data, such as [an input variable](https://opentofu.org/docs/v1.11/language/values/variables/#suppressing-values-in-cli-output) or [an output defined](https://opentofu.org/docs/v1.11/language/values/outputs/#sensitive-suppressing-values-in-cli-output) as sensitive as function arguments, the sensitive information in the arguments will be tracked during the function call. For example, passing an object containing a sensitive input variable to the `keys()` function will return a list with all keys we expected, but the `values()` function will result in a list with first item as sensitive, because the value of key "a" is sensitive. Code Block > local.baz{ "a" = (sensitive value) "b" = "dog"}> keys(local.baz)[ "a", "b",]> values(local.baz)[ (sensitive value), "dog",] When OpenTofu Calls Functions[​](https://opentofu.org/docs/v1.11/language/expressions/function-calls/#when-opentofu-calls-functions "Direct link to When OpenTofu Calls Functions") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Most of OpenTofu's built-in functions are, in programming language terms, [pure functions](https://en.wikipedia.org/wiki/Pure_function) . This means that their result is based only on their arguments and so it doesn't make any practical difference when OpenTofu would call them. However, a small subset of functions interact with outside state and so for those it can be helpful to know when OpenTofu will call them in relation to other events that occur in an OpenTofu run. The small set of special functions includes [`file`](https://opentofu.org/docs/v1.11/language/functions/file/) , [`templatefile`](https://opentofu.org/docs/v1.11/language/functions/templatefile/) , [`timestamp`](https://opentofu.org/docs/v1.11/language/functions/timestamp/) , and [`uuid`](https://opentofu.org/docs/v1.11/language/functions/uuid/) . If you are not working with these functions then you don't need to read this section, although the information here may still be interesting background information. The `file` and `templatefile` functions are intended for reading files that are included as a static part of the configuration and so OpenTofu will execute these functions as part of initial configuration validation, before taking any other actions with the configuration. That means you cannot use either function to read files that your configuration might generate dynamically on disk as part of the plan or apply steps. The `timestamp` function returns a representation of the current system time at the point when OpenTofu calls it, and the `uuid` function returns a random result which differs on each call. Without any special behavior, these would both cause the final configuration during the apply step not to match the actions shown in the plan, which violates the OpenTofu execution model. For that reason, OpenTofu arranges for both of those functions to produce [unknown value](https://opentofu.org/docs/v1.11/language/expressions/references/#values-not-yet-known) results during the plan step, with the real result being decided only during the apply step. For `timestamp` in particular, this means that the recorded time will be the instant when OpenTofu began applying the change, rather than when OpenTofu _planned_ the change. For more details on the behavior of these functions, refer to their own documentation pages. * [Available Functions](https://opentofu.org/docs/v1.11/language/expressions/function-calls/#available-functions) * [Expanding Function Arguments](https://opentofu.org/docs/v1.11/language/expressions/function-calls/#expanding-function-arguments) * [Using Sensitive Data as Function Arguments](https://opentofu.org/docs/v1.11/language/expressions/function-calls/#using-sensitive-data-as-function-arguments) * [When OpenTofu Calls Functions](https://opentofu.org/docs/v1.11/language/expressions/function-calls/#when-opentofu-calls-functions) --- # Dynamic Blocks | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/expressions/dynamic-blocks/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page `dynamic` Blocks ================ Within top-level block constructs like resources, expressions can usually be used only when assigning a value to an argument using the `name = expression` form. This covers many uses, but some resource types include repeatable _nested blocks_ in their arguments, which typically represent separate objects that are related to (or embedded within) the containing object: Code Block resource "aws_elastic_beanstalk_environment" "tfenvtest" { name = "tf-test-name" # can use expressions here setting { # but the "setting" block is always a literal block }} You can dynamically construct repeatable nested blocks like `setting` using a special `dynamic` block type, which is supported inside `resource`, `data`, `provider`, and `provisioner` blocks: Code Block resource "aws_elastic_beanstalk_environment" "tfenvtest" { name = "tf-test-name" application = "${aws_elastic_beanstalk_application.tftest.name}" solution_stack_name = "64bit Amazon Linux 2018.03 v2.11.4 running Go 1.12.6" dynamic "setting" { for_each = var.settings content { namespace = setting.value["namespace"] name = setting.value["name"] value = setting.value["value"] } }} A `dynamic` block acts much like a [`for` expression](https://opentofu.org/docs/v1.11/language/expressions/for/) , but produces nested blocks instead of a complex typed value. It iterates over a given complex value, and generates a nested block for each element of that complex value. * The label of the dynamic block (`"setting"` in the example above) specifies what kind of nested block to generate. * The `for_each` argument provides the complex value to iterate over. * The `iterator` argument (optional) sets the name of a temporary variable that represents the current element of the complex value. If omitted, the name of the variable defaults to the label of the `dynamic` block (`"setting"` in the example above). * The `labels` argument (optional) is a list of strings that specifies the block labels, in order, to use for each generated block. You can use the temporary iterator variable in this value. * The nested `content` block defines the body of each generated block. You can use the temporary iterator variable inside this block. Since the `for_each` argument accepts any collection or structural value, you can use a `for` expression or splat expression to transform an existing collection. The iterator object (`setting` in the example above) has two attributes: * `key` is the map key or list element index for the current element. If the `for_each` expression produces a _set_ value then `key` is identical to `value` and should not be used. * `value` is the value of the current element. A `dynamic` block can only generate arguments that belong to the resource type, data source, provider or provisioner being configured. It is _not_ possible to generate meta-argument blocks such as `lifecycle` and `provisioner` blocks, since OpenTofu must process these before it is safe to evaluate expressions. The `for_each` value must be a collection with one element per desired nested block. If you need to declare resource instances based on a nested data structure or combinations of elements from multiple data structures you can use OpenTofu expressions and functions to derive a suitable value. For some common examples of such situations, see the [`flatten`](https://opentofu.org/docs/v1.11/language/functions/flatten/) and [`setproduct`](https://opentofu.org/docs/v1.11/language/functions/setproduct/) functions. Multi-level Nested Block Structures[​](https://opentofu.org/docs/v1.11/language/expressions/dynamic-blocks/#multi-level-nested-block-structures "Direct link to Multi-level Nested Block Structures") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Some providers define resource types that include multiple levels of blocks nested inside one another. You can generate these nested structures dynamically when necessary by nesting `dynamic` blocks in the `content` portion of other `dynamic` blocks. For example, a module might accept a complex data structure like the following: Code Block variable "load_balancer_origin_groups" { type = map(object({ origins = set(object({ hostname = string })) }))} If you were defining a resource whose type expects a block for each origin group and then nested blocks for each origin within a group, you could ask OpenTofu to generate that dynamically using the following nested `dynamic` blocks: Code Block dynamic "origin_group" { for_each = var.load_balancer_origin_groups content { name = origin_group.key dynamic "origin" { for_each = origin_group.value.origins content { hostname = origin.value.hostname } } } } When using nested `dynamic` blocks it's particularly important to pay attention to the iterator symbol for each block. In the above example, `origin_group.value` refers to the current element of the outer block, while `origin.value` refers to the current element of the inner block. If a particular resource type defines nested blocks that have the same type name as one of their parents, you can use the `iterator` argument in each of `dynamic` blocks to choose a different iterator symbol that makes the two easier to distinguish. Best Practices for `dynamic` Blocks[​](https://opentofu.org/docs/v1.11/language/expressions/dynamic-blocks/#best-practices-for-dynamic-blocks "Direct link to best-practices-for-dynamic-blocks") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Overuse of `dynamic` blocks can make configuration hard to read and maintain, so we recommend using them only when you need to hide details in order to build a clean user interface for a re-usable module. Always write nested blocks out literally where possible. If you find yourself defining most or all of a `resource` block's arguments and nested blocks using directly-corresponding attributes from an input variable then that might suggest that your module is not creating a useful abstraction. It may be better for the calling module to define the resource itself then pass information about it into your module. For more information on this design tradeoff, see [When to Write a Module](https://opentofu.org/docs/v1.11/language/modules/develop/#when-to-write-a-module) and [Module Composition](https://opentofu.org/docs/v1.11/language/modules/develop/composition/) . * [Multi-level Nested Block Structures](https://opentofu.org/docs/v1.11/language/expressions/dynamic-blocks/#multi-level-nested-block-structures) * [Best Practices for `dynamic` Blocks](https://opentofu.org/docs/v1.11/language/expressions/dynamic-blocks/#best-practices-for-dynamic-blocks) --- # For Expressions | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/expressions/for/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page `for` Expressions ================= A _`for` expression_ creates a complex type value by transforming another complex type value. Each element in the input value can correspond to either one or zero values in the result, and an arbitrary expression can be used to transform each input element into an output element. For example, if `var.list` were a list of strings, then the following expression would produce a tuple of strings with all-uppercase letters: Code Block [for s in var.list : upper(s)] This `for` expression iterates over each element of `var.list`, and then evaluates the expression `upper(s)` with `s` set to each respective element. It then builds a new tuple value with all of the results of executing that expression in the same order. Input Types[​](https://opentofu.org/docs/v1.11/language/expressions/for/#input-types "Direct link to Input Types") ------------------------------------------------------------------------------------------------------------------- A `for` expression's input (given after the `in` keyword) can be a list, a set, a tuple, a map, or an object. The above example showed a `for` expression with only a single temporary symbol `s`, but a `for` expression can optionally declare a pair of temporary symbols in order to use the key or index of each item too: Code Block [for k, v in var.map : length(k) + length(v)] For a map or object type, like above, the `k` symbol refers to the key or attribute name of the current element. You can also use the two-symbol form with lists and tuples, in which case the additional symbol is the index of each element starting from zero, which conventionally has the symbol name `i` or `idx` unless it's helpful to choose a more specific name: Code Block [for i, v in var.list : "${i} is ${v}"] The index or key symbol is always optional. If you specify only a single symbol after the `for` keyword then that symbol will always represent the _value_ of each element of the input collection. Result Types[​](https://opentofu.org/docs/v1.11/language/expressions/for/#result-types "Direct link to Result Types") ---------------------------------------------------------------------------------------------------------------------- The type of brackets around the `for` expression decide what type of result it produces. The above example uses `[` and `]`, which produces a tuple. If you use `{` and `}` instead, the result is an object and you must provide two result expressions that are separated by the `=>` symbol: Code Block {for s in var.list : s => upper(s)} This expression produces an object whose attributes are the original elements from `var.list` and their corresponding values are the uppercase versions. For example, the resulting value might be as follows: Code Block { foo = "FOO" bar = "BAR" baz = "BAZ"} A `for` expression alone can only produce either an object value or a tuple value, but OpenTofu's automatic type conversion rules mean that you can typically use the results in locations where lists, maps, and sets are expected. Filtering Elements[​](https://opentofu.org/docs/v1.11/language/expressions/for/#filtering-elements "Direct link to Filtering Elements") ---------------------------------------------------------------------------------------------------------------------------------------- A `for` expression can also include an optional `if` clause to filter elements from the source collection, producing a value with fewer elements than the source value: Code Block [for s in var.list : upper(s) if s != ""] One common reason for filtering collections in `for` expressions is to split a single source collection into two separate collections based on some criteria. For example, if the input `var.users` is a map of objects where the objects each have an attribute `is_admin` then you may wish to produce separate maps with admin vs non-admin objects: Code Block variable "users" { type = map(object({ is_admin = bool }))}locals { admin_users = { for name, user in var.users : name => user if user.is_admin } regular_users = { for name, user in var.users : name => user if !user.is_admin }} Element Ordering[​](https://opentofu.org/docs/v1.11/language/expressions/for/#element-ordering "Direct link to Element Ordering") ---------------------------------------------------------------------------------------------------------------------------------- Because `for` expressions can convert from unordered types (maps, objects, sets) to ordered types (lists, tuples), OpenTofu must choose an implied ordering for the elements of an unordered collection. For maps and objects, OpenTofu sorts the elements by key or attribute name, using lexical sorting. For sets of strings, OpenTofu sorts the elements by their value, using lexical sorting. For sets of other types, OpenTofu uses an arbitrary ordering that may change in future versions. We recommend converting the expression result into a set to make it clear elsewhere in the configuration that the result is unordered. You can use [the `toset` function](https://opentofu.org/docs/v1.11/language/functions/toset/) to concisely convert a `for` expression result to be of a set type. Code Block toset([for e in var.set : e.example]) Grouping Results[​](https://opentofu.org/docs/v1.11/language/expressions/for/#grouping-results "Direct link to Grouping Results") ---------------------------------------------------------------------------------------------------------------------------------- If the result type is an object (using `{` and `}` delimiters) then normally the given key expression must be unique across all elements in the result, or OpenTofu will return an error. Sometimes the resulting keys are _not_ unique, and so to support that situation OpenTofu supports a special _grouping mode_ which changes the result to support multiple elements per key. To activate grouping mode, add the symbol `...` after the value expression. For example: Code Block variable "users" { type = map(object({ role = string }))}locals { users_by_role = { for name, user in var.users : user.role => name... }} The above represents a situation where a module expects a map describing various users who each have a single "role", where the map keys are usernames. The usernames are guaranteed unique because they are map keys in the input, but many users may all share a single role name. The `local.users_by_role` expression inverts the input map so that the keys are the role names and the values are usernames, but the expression is in grouping mode (due to the `...` after `name`) and so the result will be a map of lists of strings, such as the following: Code Block { "admin": [ "ps", ], "maintainer": [ "am", "jb", "kl", "ma", ], "viewer": [ "st", "zq", ],} Due to [the element ordering rules](https://opentofu.org/docs/v1.11/language/expressions/for/#element-ordering) , OpenTofu will sort the users lexically by username as part of evaluating the `for` expression, and so the usernames associated with each role will be lexically sorted after grouping. Repeated Configuration Blocks[​](https://opentofu.org/docs/v1.11/language/expressions/for/#repeated-configuration-blocks "Direct link to Repeated Configuration Blocks") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The `for` expressions mechanism is for constructing collection values from other collection values within expressions, which you can then assign to individual resource arguments that expect complex values. Some resource types also define _nested block types_, which typically represent separate objects that belong to the containing resource in some way. You can't dynamically generate nested blocks using `for` expressions, but you _can_ generate nested blocks for a resource dynamically using [`dynamic` blocks](https://opentofu.org/docs/v1.11/language/expressions/dynamic-blocks/) . * [Input Types](https://opentofu.org/docs/v1.11/language/expressions/for/#input-types) * [Result Types](https://opentofu.org/docs/v1.11/language/expressions/for/#result-types) * [Filtering Elements](https://opentofu.org/docs/v1.11/language/expressions/for/#filtering-elements) * [Element Ordering](https://opentofu.org/docs/v1.11/language/expressions/for/#element-ordering) * [Grouping Results](https://opentofu.org/docs/v1.11/language/expressions/for/#grouping-results) * [Repeated Configuration Blocks](https://opentofu.org/docs/v1.11/language/expressions/for/#repeated-configuration-blocks) --- # lifecycle Blocks | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/meta-arguments/lifecycle/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) `lifecycle` Blocks ================== Several different declaration types in the OpenTofu language support a nested block named `lifecycle` which includes settings that customize the plan and apply behavior of the associated object. Each different type of declaration relates to objects that have a different lifecycle, and so the arguments available in these blocks are distinct for each parent block type: * [`resource` block lifecycle](https://opentofu.org/docs/v1.11/language/resources/behavior/#lifecycle-customizations) , for managed resources. * [`data` block lifecycle](https://opentofu.org/docs/v1.11/language/data-sources/#lifecycle-customizations) , for data resources. * [`ephemeral` block lifecycle](https://opentofu.org/docs/v1.11/language/ephemerality/ephemeral-resources/#lifecycle-customizations) , for ephemeral resources. * [`module` block lifecycle](https://opentofu.org/docs/v1.11/language/modules/syntax/#module-lifecycle) , for settings that relate to an overall module call instead of the individual resources inside it. Although all of these features involve a block type named `lifecycle`, the expected arguments and associated behavior is defined separately for each context where a block of that type is allowed to appear. --- # Publishing Modules | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/modules/develop/publish/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Publishing Modules ================== If you've built a module that you intend to be reused, we recommend [publishing the module](https://github.com/opentofu/registry/issues/new/choose) on the [Public OpenTofu Registry](https://registry.opentofu.org/) . This will version your module, generate documentation, and more. Published modules can be easily consumed by OpenTofu, and users can [constrain module versions](https://opentofu.org/docs/v1.11/language/modules/syntax/#version) for safe and predictable updates. The following example shows how a caller might use a module from the Module Registry: Code Block module "consul" { source = "hashicorp/consul/aws"} If you do not wish to publish your modules in the public registry, you can instead use a [private registry](https://opentofu.org/docs/v1.11/internals/module-registry-protocol/) to get the same benefits. We welcome contributions of modules from our community members, partners, and customers. Our ecosystem is made richer by each new module created or an existing one updated, as they reflect the wide range of experience and technical requirements of the community that uses them. Our cloud provider partners often seek to develop specific modules for popular or challenging use cases on their platform and utilize them as valuable learning experiences to empathize with their users. Similarly, our community module developers incorporate a variety of opinions and use cases from the broader OpenTofu community. Both types of modules have their place in the registry, accessible to practitioners who can decide which modules best fit their requirements. Distribution via other sources[​](https://opentofu.org/docs/v1.11/language/modules/develop/publish/#distribution-via-other-sources "Direct link to Distribution via other sources") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Although the registry is the native mechanism for distributing re-usable modules, OpenTofu can also install modules from [various other sources](https://opentofu.org/docs/v1.11/language/modules/sources/) . The alternative sources do not support the first-class versioning mechanism, but some sources have their own mechanisms for selecting particular VCS commits, etc. We recommend that modules distributed via other protocols still use the [standard module structure](https://opentofu.org/docs/v1.11/language/modules/develop/structure/) so that they can be used in a similar way as a registry module or be published on the registry at a later time. * [Distribution via other sources](https://opentofu.org/docs/v1.11/language/modules/develop/publish/#distribution-via-other-sources) --- # Generating configuration | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Generating configuration ======================== Experimental Configuration generation is available in OpenTofu v1.6 as an experimental feature. Later minor versions may contain changes to the formatting of generated configuration and behavior of the `tofu plan` command using the `-generate-config-out` flag. OpenTofu can generate code for the resources you define in [`import` blocks](https://opentofu.org/docs/v1.11/language/import/) that do not already exist in your configuration. OpenTofu produces HCL to act as a template that contains OpenTofu's best guess at the appropriate value for each resource argument. Starting with OpenTofu's generated HCL, we recommend iterating to find your ideal configuration by removing some attributes, adjusting the value of others, and rearranging `resource` blocks into files and modules as appropriate. To generate configuration, run `tofu plan` with the `-generate-config-out` flag and supply a new file path. Do not supply a path to an existing file, or OpenTofu throws an error. Code Block $ tofu plan -generate-config-out=generated_resources.tf If any resources targeted by an `import` block do not exist in your configuration, OpenTofu then generates and writes configuration for those resources in `generated_resources.tf`. Workflow[​](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#workflow "Direct link to Workflow") -------------------------------------------------------------------------------------------------------------------------- The workflow for generating configuration is similar to the [`import` block workflow](https://opentofu.org/docs/v1.11/language/import/#plan-and-apply-an-import) , with the extra step of generating configuration during the planning stage. You can then review and modify the generated configuration before applying. ### 1\. Add the `import` block[​](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#1-add-the-import-block "Direct link to 1-add-the-import-block") Add an `import` block to your configuration. This `import` block can be in a separate file (e.g., `import.tf`) or an existing configuration file. Code Block import { to = aws_iot_thing.bar id = "foo"} The import block's `to` argument points to the address a `resource` will have in your state file. If a resource address in your state matches an `import` block's `to` argument, OpenTofu attempts to import into that resource. In future planning, OpenTofu knows it doesn't need to generate configuration for resources that already exist in your state. The import block's `id` argument uses that resource's [import ID](https://opentofu.org/docs/v1.11/language/import/#import-id) . If your configuration does not contain other resources for your selected provider, you must add a `provider` block to inform OpenTofu which provider it should use to generate configuration. Otherwise, OpenTofu displays an error if it can not determine which provider to use. If you add a new `provider` block to your configuration, you must run `tofu init` again. ### 2\. Plan and generate configuration[​](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#2-plan-and-generate-configuration "Direct link to 2. Plan and generate configuration") To instruct OpenTofu to generate configuration for the `import` blocks you defined, run `tofu plan` with the `-generate-config-out=` flag and a new file path. OpenTofu displays its plan for importing your resource and the file where OpenTofu generated configuration based on this plan. Code Block $ tofu plan -generate-config-out=generated.tfaws_iot_thing.bar: Preparing import... [id=foo]aws_iot_thing.bar: Refreshing state... [id=foo]OpenTofu will perform the following actions: # aws_iot_thing.bar will be imported # (config will be generated) resource "aws_iot_thing" "bar" { arn = "arn:aws:iot:eu-west-1:1234567890:thing/foo" attributes = {} default_client_id = "foo" id = "foo" name = "foo" version = 1 }Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.β•·β”‚ Warning: Config generation is experimentalβ”‚ β”‚ Generating configuration during import is currently experimental, and the generated configuration format may change in future versions.╡──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────OpenTofu has generated configuration and written it to generated.tf. Please review the configuration and edit it as necessary before adding it to version control. ### 3\. Review generated configuration[​](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#3-review-generated-configuration "Direct link to 3. Review generated configuration") The example above instructs OpenTofu to generate configuration in a file named `generated.tf`. The below code is an example of a `generated.tf` file. Code Block resource aws_iot_thing "bar" { name = "foo"} Review the generated configuration and update it as needed. You may wish to move the generated configuration to another file, add or remove resource arguments, or update it to reference input variables or other resources in your configuration. #### Generated hints[​](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#generated-hints "Direct link to Generated hints") In specific cases, the attributes of the generated blocks can be suffixed with a comment. That comment may contain hints as to why a value was omitted. For example, the following will be generated if the generated `resource` block contains sensitive and write-only attributes: Code Block resource "test_resource" "test" { attr1 = null # sensitive attr2 = null # write-only attr3 = null # sensitive write-only} ### 4\. Apply[​](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#4-apply "Direct link to 4. Apply") Run `tofu apply` to import your infrastructure. Code Block $ tofu applyaws_iot_thing.bar: Preparing import... [id=foo]aws_iot_thing.bar: Refreshing state... [id=foo]OpenTofu will perform the following actions: # aws_iot_thing.bar will be imported resource "aws_iot_thing" "bar" { arn = "arn:aws:iot:eu-west-1:1234567890:thing/foo" attributes = {} default_client_id = "foo" id = "foo" name = "foo" version = 1 }Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.aws_iot_thing.bar: Importing... [id=foo]aws_iot_thing.bar: Import complete [id=foo]Apply complete! Resources: 1 imported, 0 added, 0 changed, 0 destroyed. Commit your new resource configuration to your version control system. Limitations[​](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#limitations "Direct link to Limitations") ----------------------------------------------------------------------------------------------------------------------------------- ### Conflicting resource arguments[​](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#conflicting-resource-arguments "Direct link to Conflicting resource arguments") OpenTofu generates configuration for importable resources during a plan by requesting values for resource attributes from the provider. For certain resources with complex schemas, OpenTofu may not be able to construct a valid configuration from these values. OpenTofu will display an error like the one below if it does not receive values for resource attributes while generating configuration. Code Block $ tofu plan -generate-config-out=generated.tfβ•·β”‚ Error: Conflicting configuration argumentsβ”‚ β”‚ with aws_instance.ubuntu,β”‚ on g.tf line 20, in resource "aws_instance" "ubuntu":β”‚ 20: ipv6_address_count = 0β”‚ β”‚ "ipv6_address_count": conflicts with ipv6_addressesβ•΅ In the example above, OpenTofu still generates configuration and writes it to `generated.tf`. This error stems from a conflict between the `ipv6_address_count` and `ipv6_addresses` arguments. The resource supports both of these arguments, but you must choose only one when configuring the resource. You could fix the error by removing one of these two arguments, then running `tofu plan` again to check that there are no further issues. * [Workflow](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#workflow) * [1\. Add the `import` block](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#1-add-the-import-block) * [2\. Plan and generate configuration](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#2-plan-and-generate-configuration) * [3\. Review generated configuration](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#3-review-generated-configuration) * [4\. Apply](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#4-apply) * [Limitations](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#limitations) * [Conflicting resource arguments](https://opentofu.org/docs/v1.11/language/import/generating-configuration/#conflicting-resource-arguments) --- # OpenTofu vs. Chef, Puppet, etc. | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.6/intro/vs/chef-puppet/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) This is documentation for OpenTofu **1.6.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://opentofu.org/docs/v1.11/) ** (1.11.x). OpenTofu vs. Chef, Puppet, etc. =============================== Configuration management tools install and manage software on a machine that already exists. OpenTofu is not a configuration management tool, and it allows existing tooling to focus on their strengths: bootstrapping and initializing resources. OpenTofu focuses on the higher-level abstraction of the datacenter and associated services, while allowing you to use configuration management tools on individual systems. It also aims to bring the same benefits of codification of your system configuration to infrastructure management. If you are using traditional configuration management within your compute instances, you can use OpenTofu to configure bootstrapping software like cloud-init to activate your configuration management software on first system boot. --- # Command: state mv | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Command: state mv ================= The main function of [OpenTofu state](https://opentofu.org/docs/v1.11/language/state/) is to track the bindings between resource instance addresses in your configuration and the remote objects they represent. Normally OpenTofu automatically updates the state in response to actions taken when applying a plan, such as removing a binding for an remote object that has now been deleted. You can use `tofu state mv` in the less common situation where you wish to retain an existing remote object but track it as a different resource instance address in OpenTofu, such as if you have renamed a resource block or you have moved it into a different module in your configuration. Usage[​](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#usage "Direct link to Usage") ---------------------------------------------------------------------------------------------- Usage: `tofu state mv [options] SOURCE DESTINATION` OpenTofu will look in the current state for a resource instance, resource, or module that matches the given address, and if successful it will move the remote objects currently associated with the source to be tracked instead by the destination. Both the source and destination addresses must use [resource address syntax](https://opentofu.org/docs/v1.11/cli/state/resource-addressing/) , and they must both refer to the same kind of object: you can only move a resource instance to another resource instance, a whole module instance to another whole module instance, etc. Furthermore, if you are moving a resource or a resource instance then you can only move it to a new address with the same resource type. The most common uses for `tofu state mv` are when you have renamed a resource block in your configuration or you've moved a resource block into a child module, in both cases with the intention of retaining the existing object but tracking it under a new name. By default OpenTofu will understand moving or renaming a resource configuration as a request to delete the old object and create a new object at the new address, and so `tofu state mv` allows you to override that interpretation by pre-emptively attaching the existing object to the new address in OpenTofu. Warning If you are using OpenTofu in a collaborative environment, you must ensure that when you are using `tofu state mv` for a code refactoring purpose you communicate carefully with your coworkers to ensure that nobody makes any other changes between your configuration change and your `tofu state mv` command, because otherwise they might inadvertently create a plan that will destroy the old object and create a new object at the new address. Note Use of variables in [module sources](https://opentofu.org/docs/v1.11/language/modules/sources/#support-for-variable-and-local-evaluation) , [backend configuration](https://opentofu.org/docs/v1.11/language/settings/backends/configuration/#variables-and-locals) , or [encryption block](https://opentofu.org/docs/v1.11/language/state/encryption/#configuration) requires [assigning values to root module variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) when running `tofu state mv`. This command also accepts the following options: * `-dry-run` - Report all of the resource instances that match the given address without actually "forgetting" any of them. * `-lock=false` - Don't hold a state lock during the operation. This is dangerous if others might concurrently run commands against the same workspace. * `-lock-timeout=DURATION` - Unless locking is disabled with `-lock=false`, instructs OpenTofu to retry acquiring a lock for a period of time before returning an error. The duration syntax is a number followed by a time unit letter, such as "3s" for three seconds. * `-var 'NAME=VALUE'` - Sets a value for a single [input variable](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration. Use this option multiple times to set more than one variable. Refer to [Input Variables on the Command Line](https://opentofu.org/docs/v1.11/cli/commands/plan/#input-variables-on-the-command-line) for more information. * `-var-file=FILENAME` - Sets values for potentially many [input variables](https://opentofu.org/docs/v1.11/language/values/variables/) declared in the root module of the configuration, using definitions from a ["tfvars" file](https://opentofu.org/docs/v1.11/language/values/variables/#variable-definitions-tfvars-files) . Use this option multiple times to include values from more than one file. There are several other ways to set values for input variables in the root module, aside from the `-var` and `-var-file` options. Refer to [Assigning Values to Root Module Variables](https://opentofu.org/docs/v1.11/language/values/variables/#assigning-values-to-root-module-variables) for more information. For configurations using the [`cloud` backend](https://opentofu.org/docs/v1.11/cli/cloud/) or the [`remote` backend](https://opentofu.org/docs/v1.11/language/settings/backends/remote/) only, `tofu state mv` also accepts the option [`-ignore-remote-version`](https://opentofu.org/docs/v1.11/cli/cloud/command-line-arguments/#ignore-remote-version) . The legacy options [`-backup` and `-backup-out`](https://opentofu.org/docs/v1.11/language/settings/backends/local/#command-line-arguments) operate on a local state file only. Configurations using [the `remote` backend](https://opentofu.org/docs/v1.11/language/settings/backends/remote/) must specify a local state file with the [`-state`](https://opentofu.org/docs/v1.11/language/settings/backends/local/#command-line-arguments) option in order to use the [`-backup` and `-backup-out`](https://opentofu.org/docs/v1.11/language/settings/backends/local/#command-line-arguments) options. For configurations using [the `local` state mv](https://opentofu.org/docs/v1.11/language/settings/backends/local/) only, `tofu state mv` also accepts the legacy options [`-state`, `-state-out`, `-backup`, and `-backup-out`](https://opentofu.org/docs/v1.11/language/settings/backends/local/#command-line-arguments) . Example: Rename a Resource[​](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#example-rename-a-resource "Direct link to Example: Rename a Resource") ------------------------------------------------------------------------------------------------------------------------------------------------------------ Renaming a resource means making a configuration change like the following: Code Block -resource "packet_device" "worker" {+resource "packet_device" "helper" { # ... } To tell OpenTofu that it should treat the new "helper" resource as a rename of the old "worker" resource, you can pair the above configuration change with the following command: Code Block tofu state mv packet_device.worker packet_device.helper Example: Move a Resource Into a Module[​](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#example-move-a-resource-into-a-module "Direct link to Example: Move a Resource Into a Module") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ If you originally wrote a resource in your root module but now wish to refactor it into a child module, you can move the `resource` block into the child module configuration, removing the original in the root module, and then run the following command to tell OpenTofu to treat it as a move: Code Block tofu state mv packet_device.worker module.worker.packet_device.worker In the above example the new resource has the same name but a different module address. You could also change the resource name at the same time, if the new module organization suggests a different naming scheme: Code Block tofu state mv packet_device.worker module.worker.packet_device.main Example: Move a Module Into a Module[​](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#example-move-a-module-into-a-module "Direct link to Example: Move a Module Into a Module") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ You can also refactor an entire module into a child module. In the configuration, move the `module` block representing the module into a different module and then pair that change with a command like the following: Code Block tofu state mv module.app module.parent.module.app Example: Move a Particular Instance of a Resource using `count`[​](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#example-move-a-particular-instance-of-a-resource-using-count "Direct link to example-move-a-particular-instance-of-a-resource-using-count") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A resource defined with [the `count` meta-argument](https://opentofu.org/docs/v1.11/language/meta-arguments/count/) has multiple instances that are each identified by an integer. You can select a particular instance by including an explicit index in your given address: Code Block $ tofu state mv 'packet_device.worker[0]' 'packet_device.helper[0]' A resource that doesn't use `count` or `for_each` has only a single resource instance whose address is the same as the resource itself, and so you can move from an address not containing an index to an address containing an index, or the opposite, as long as the address type you use matches whether and how each resource is configured: Code Block $ tofu state mv 'packet_device.main' 'packet_device.all[0]' Brackets (`[`, `]`) have a special meaning in some shells, so you may need to quote or escape the address in order to pass it literally to OpenTofu. The above examples show the typical quoting syntax for Unix-style shells. Example: Move a Resource configured with for\_each[​](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#example-move-a-resource-configured-with-for_each "Direct link to Example: Move a Resource configured with for_each") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A resource defined with [the `for_each` meta-argument](https://opentofu.org/docs/v1.11/language/meta-arguments/for_each/) has multiple instances that are each identified by an string. You can select a particular instance by including an explicit key in your given address. However, the syntax for strings includes quotes and the quote symbol often has special meaning in command shells, so you'll need to use the appropriate quoting and/or escaping syntax for the shell you are using. For example: Unix-style shells, such as on Linux or macOS: Code Block tofu state mv 'packet_device.worker["example123"]' 'packet_device.helper["example456"]' Windows Command Prompt (`cmd.exe`): Code Block tofu state mv packet_device.worker[\"example123\"] packet_device.helper[\"example456\"] PowerShell: Code Block tofu state mv 'packet_device.worker[\"example123\"]' 'packet_device.helper[\"example456\"]' Aside from the use of strings instead of integers for instance keys, the treatment of `for_each` resources is similar to `count` resources and so the same combinations of addresses with and without index components is valid as described in the previous section. * [Usage](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#usage) * [Example: Rename a Resource](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#example-rename-a-resource) * [Example: Move a Resource Into a Module](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#example-move-a-resource-into-a-module) * [Example: Move a Module Into a Module](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#example-move-a-module-into-a-module) * [Example: Move a Particular Instance of a Resource using `count`](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#example-move-a-particular-instance-of-a-resource-using-count) * [Example: Move a Resource configured with for\_each](https://opentofu.org/docs/v1.11/cli/commands/state/mv/#example-move-a-resource-configured-with-for_each) --- # Strings and Templates | OpenTofu [Skip to main content](https://opentofu.org/docs/v1.11/language/expressions/strings/#__docusaurus_skipToContent_fallback) [πŸŽ‰ OpenTofu 1.11.0 has arrived! β†’](https://opentofu.org/blog/opentofu-1-11-0/) On this page Strings and Templates ===================== String literals are the most complex kind of literal expression in OpenTofu, and also the most commonly used. OpenTofu supports both a quoted syntax and a "heredoc" syntax for strings. Both of these syntaxes support template sequences for interpolating values and manipulating text. Quoted Strings[​](https://opentofu.org/docs/v1.11/language/expressions/strings/#quoted-strings "Direct link to Quoted Strings") -------------------------------------------------------------------------------------------------------------------------------- A quoted string is a series of characters delimited by straight double-quote characters (`"`). Code Block "hello" ### Escape Sequences[​](https://opentofu.org/docs/v1.11/language/expressions/strings/#escape-sequences "Direct link to Escape Sequences") In quoted strings, the backslash character serves as an escape sequence, with the following characters selecting the escape behavior: | Sequence | Replacement | | --- | --- | | `\n` | Newline | | `\r` | Carriage Return | | `\t` | Tab | | `\"` | Literal quote (without terminating the string) | | `\\` | Literal backslash | | `\uNNNN` | Unicode character from the basic multilingual plane (NNNN is four hex digits) | | `\UNNNNNNNN` | Unicode character from supplementary planes (NNNNNNNN is eight hex digits) | There are also two special escape sequences that do not use backslashes: | Sequence | Replacement | | --- | --- | | `$${` | Literal `${`, without beginning an interpolation sequence. | | `%%{` | Literal `%{`, without beginning a template directive sequence. | Heredoc Strings[​](https://opentofu.org/docs/v1.11/language/expressions/strings/#heredoc-strings "Direct link to Heredoc Strings") ----------------------------------------------------------------------------------------------------------------------------------- OpenTofu also supports a "heredoc" style of string literal inspired by Unix shell languages, which allows multi-line strings to be expressed more clearly. Code Block <}`/`%{else}`/`%{endif}` directive chooses between two templates based on the value of a bool expression: Code Block "Hello, %{ if var.name != "" }${var.name}%{ else }unnamed%{ endif }!" The `else` portion may be omitted, in which case the result is an empty string if the condition expression returns `false`. * The `%{for in }` / `%{endfor}` directive iterates over the elements of a given collection or structural value and evaluates a given template once for each element, concatenating the results together: Code Block <