Skip to main content

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 page documents how to declare providers so OpenTofu can install them.

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 and Module Development: Providers Within Modules.)

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 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 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, 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:

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

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

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

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

Each resource in your OpenTofu configuration must be bound to one provider configuration.

By default, each resource is bound to a default provider configuration 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, with a provider instance reference 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

To explicitly refer to provider configurations, OpenTofu uses a provider-configuration-specific reference syntax of the form <PROVIDER NAME>.<ALIAS>. For example, aws.west refers to the provider "aws" block with alias = "west".

This syntax uses similar symbols to a normal expression reference, but provider references are not normal expressions and can only be used in some special locations:

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, 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 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.

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.

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. 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.