---
description: >-
  An overview of how to install and use providers, OpenTofu plugins that
  interact with services, cloud providers, and other APIs.
---

# 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

Each provider adds a set of [resource types](../../language/resources/index.mdx)
and/or [data sources](../../language/data-sources/index.mdx) 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

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

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

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](../../language/providers/requirements.mdx)
  documents how to declare providers so OpenTofu can install them.

- [Provider Configuration](../../language/providers/configuration.mdx)
  documents how to configure settings for providers.

- [Dependency Lock File](../../language/files/dependency-lock.mdx)
  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

- [TACOS](../../intro/tacos.mdx) (TF Automation and Collaboration Software) install providers as part of every run.

- OpenTofu CLI finds and installs providers when
  [initializing a working directory](../../cli/init/index.mdx). 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](../../cli/config/config-file.mdx).

To ensure OpenTofu always installs the same provider versions for a given
configuration, you can use OpenTofu CLI to create a
[dependency lock file](../../language/files/dependency-lock.mdx)
and commit it to version control along with your configuration. If a lock file
is present, OpenTofu CLI, and [TACOS](../../intro/tacos.mdx) (TF Automation and Collaboration Software) will all obey it when
installing providers.

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

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

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:

```
TF_ACC_TERRAFORM_PATH="/path/to/opentofu"
TF_ACC_PROVIDER_NAMESPACE="hashicorp"
TF_ACC_PROVIDER_HOST="registry.opentofu.org"
```

#### Known Divergences

##### Ephemeral Resources in Plan Output

OpenTofu includes [ephemeral resources](../../language/ephemerality/ephemeral-resources.mdx) with an `open` action in the JSON plan output's `resource_changes`. This is needed internally for building the apply execution graph when running `tofu apply <planfile>`.

OpenTofu's internal plan emptiness check correctly ignores `open` actions — so the CLI output will say "No changes" and `-detailed-exitcode` returns `0`. However, the [`terraform-plugin-testing`](https://github.com/hashicorp/terraform-plugin-testing) framework interprets any entry in `resource_changes` as a non-empty plan, which can cause acceptance test failures when ephemeral resources are present.

The recommended workaround is to conditionally set `ExpectNonEmptyPlan` when running against OpenTofu. First, add a helper to detect OpenTofu:

```go
// UsingOpenTofu reports whether the acceptance test binary is OpenTofu.
// OpenTofu includes ephemeral resource "open" actions in the JSON plan's
// resource_changes, which causes terraform-plugin-testing to consider the
// plan non-empty. See: https://github.com/opentofu/opentofu/issues/3781
func UsingOpenTofu() bool {
	return strings.HasSuffix(os.Getenv("TF_ACC_TERRAFORM_PATH"), "tofu")
}
```

Then on any test step that includes ephemeral resources:

```go
{
	Config:             testConfig,
	ExpectNonEmptyPlan: UsingOpenTofu(),
},
```

If you run acceptance tests against both OpenTofu and Terraform, you can use `SkipFunc` to define separate steps for each:

```go
isTofu := UsingOpenTofu()

// Step for OpenTofu
{
	Config:             testConfig,
	ExpectNonEmptyPlan: true,
	SkipFunc: func() (bool, error) {
		return !isTofu, nil
	},
},
// Step for Terraform
{
	Config:             testConfig,
	ExpectNonEmptyPlan: false,
	SkipFunc: func() (bool, error) {
		return isTofu, nil
	},
},
```