---
sidebar_position: 1
sidebar_label: Provider Configuration
description: >-
  Learn how to set up providers, including how to use the alias meta-argument to
  specify multiple configurations for a single provider.
---

import CodeBlock from '@theme/CodeBlock';
import ExampleDynamicProviderInstances from '!!raw-loader!../meta-arguments/examples/resource-provider-dynamic-instances.tf'

# 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](requirements.mdx)
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](../../language/meta-arguments/module-providers.mdx)
and [Module Development: Providers Within Modules](../../language/modules/develop/providers.mdx).)

A provider configuration is defined using a `provider` block:

```hcl
provider "google" {
  project = "acme-app"
  region  = "us-central1"
}
```

The name given in the block header (`"google"` in this example) is the
[local name](../../language/providers/requirements.mdx#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](../../language/expressions/index.mdx) 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.

You can use [ephemeral values](../ephemerality/index.mdx) to configure a provider. These can come
from multiple places, such as variables, outputs or ephemeral resources.
A provider configuration example is included in the [ephemeral documentation](../ephemerality/index.mdx#using-the-module-in-a-configuration-to-retrieve-a-secret-and-configure-a-provider).

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][inpage-alias]
- [`for_each`, for defining multiple dynamic instances of a provider configuration][inpage-for_each]
- [`version`, which we no longer recommend][inpage-versions] (use
  [provider requirements](../../language/providers/requirements.mdx) 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

[inpage-alias]: #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:

```hcl
# 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:

```hcl
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

[inpage-for_each]: #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:

```hcl
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:

```hcl
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](#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](../../language/meta-arguments/resource-provider.mdx),
with a [provider instance reference](#referring-to-provider-instances)
that includes the selected configuration's alias:

```hcl
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:

```hcl
resource "aws_instance" "foo" {
  provider = aws

  # ...
}
```

## Referring to Provider Instances

{/* old section anchor to preserve existing external links */}
<a id="referring-to-alternate-provider-configurations"></a>

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](../../language/expressions/references.mdx), 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](../../language/meta-arguments/resource-provider.mdx)
- [The `providers` meta-argument of a `module` block](../../language/meta-arguments/module-providers.mdx)

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](../../language/expressions/index.mdx),
and typically the instance key would be selected dynamically for each
instance of a resource rather than hard-coded. For example:

<CodeBlock language="hcl">{ExampleDynamicProviderInstances}</CodeBlock>

{/* NOTE: The above example is shared with ../meta-arguments/resource-provider.mdx */}

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](../../language/meta-arguments/module-providers.mdx#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 *be different* from 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.
:::

### Deleting a provider instance

One main limitation of the provider instances feature is that removing a provider instance requires extra rounds of planning and applying. The following example illustrates this issue and how to avoid it.

As explained above, a resource should always use a `for_each` expression that is a subset of the provider configuration's `for_each`. In the following configuration, both the provider and the resource use the same `for_each` value:

```
variable "aws_active_regions" {
  type    = set(string)
  default = ["us-east-1", "sa-east-1"]
}

provider "aws" {
  alias    = "by_region"
  for_each = var.aws_active_regions
  region   = each.key
}

resource "aws_cloudwatch_log_group" "lambda_cloudfront" {
  name     = "/aws/lambda/${each.key}.lambda"
  provider = aws.by_region[each.key]
  for_each = var.aws_active_regions
}
```

This configuration will produce the following warning:

```
╷
│ Warning: Provider configuration for_each matches resource
│
│   on main.tf line 24, in resource "aws_cloudwatch_log_group" "lambda_cloudfront":
│   24:   for_each = var.aws_regions
│
│ This provider configuration uses the same for_each expression as a
│ resource, which means that subsequent removal of elements from this
│ collection would cause a planning error.
│
│ OpenTofu relies on a provider instance to destroy resource instances
│ that are associated with it, and so the provider instance must
│ outlive all of its resource instances by at least one plan/apply
│ round. For removal of instances to succeed in future you must
│ structure the configuration so that the provider block's for_each
│ expression can produce a superset of the instances of the resources
│ associated with the provider configuration. Refer to the OpenTofu
│ documentation for specific suggestions.
│
│ To destroy this object before removing the provider configuration,
│ consider first performing a targeted destroy:
│     tofu apply -destroy -target=aws_cloudwatch_log_group.lambda_cloudfront
╵
```

This approach is error-prone because you must run `apply -destroy -target` for all resources associated with the provider instance before you can remove the provider instance itself. If you try to remove the provider instance by deleting the key from `aws_active_regions` before destroying the resources, OpenTofu will prevent you:

```
╷
│ Error: Provider instance not present
│
│ To work with aws_cloudwatch_log_group.lambda_cloudfront["sa-east-1"]
│ its original provider instance at
│ provider["registry.opentofu.org/hashicorp/aws"].by_region["sa-east-1"]
│ is required, but it has been removed. This occurs when an element is
│ removed from the provider configuration's for_each collection while
│ objects created by that the associated provider instance still exist
│ in the state. Re-add the for_each element to destroy
│ aws_cloudwatch_log_group.lambda_cloudfront["sa-east-1"], after which
│ you can remove the provider configuration again.
│
│ This is commonly caused by using the same for_each collection both
│ for a resource (or its containing module) and its associated provider
│ configuration. To successfully remove an instance of a resource it
│ must be possible to remove the corresponding element from the
│ resource's for_each collection while retaining the corresponding
│ element in the provider's for_each collection.
╵
```

An alternative approach is to use a different subset for the resource's `for_each` expression:

```hcl
variable "aws_active_regions" {
  type = set(string)
  default = ["us-east-1", "sa-east-1"]
}

variable "aws_disabled_regions" {
  description = "A list of regions that should be disabled and all resources removed."
  type        = set(string)
  default     = []
}

// Superset of the provider configuration
provider "aws" {
  alias    = "by_region"
  for_each = var.aws_active_regions
  region   = each.key
}

// Resource using a subset of the provider's configuration
resource "aws_cloudwatch_log_group" "lambda_cloudfront" {
  name     = "/aws/lambda/${each.key}.lambda"
  provider = aws.by_region[each.key]
  for_each = setsubtract(var.aws_active_regions, var.aws_disabled_regions)
}
```

If you need to remove a provider instance (for example, for a specific AWS region), add that region to `aws_disabled_regions`:
```
variable "aws_disabled_regions" {
  description = "A list of regions that should be disabled and all resources removed."
  type        = set(string)
  default     = ["us-east-1"]
}
```

With this approach, running `tofu plan` and `tofu apply` is sufficient to disable the provider instance and remove all associated resources.

### 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](../../language/meta-arguments/module-providers.mdx).

<a id="provider-versions"></a>

## `version` (Deprecated)
<!-- TODO: Figure out the best way to link to this, or remove the deprecated setting documentation completely -->
<!-- lint ignore  remark-lint-no-undefined-references -->

[inpage-versions]: #provider-versions

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](../../language/providers/requirements.mdx). 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](../../language/providers/requirements.mdx).
