Provider block
A provider block is a plugin that enables Terraform to interact with your infrastructure, such as AWS, GCP, or Azure. It acts like a bridge between the Terraform configuration code and your actual infrastructure, carrying out all the necessary
CRUD
on your infrastructure resources. Each provider contains two kinds of main components: resource blocks, which are used to perform create, update, and delete operations and datasource blocks, which are used to fetch information about existing resources on your infrastructure.
Providers are distributed separately from Terraform itself. They each have their own release schedules and version numbers, so you must ensure you are using the appropriate version of the provider for your Terraform configuration. Terraform Registry is the main directory of publicly available providers including ones developed by HashiCorp, third-party vendors, and the Terraform community.
Provider block syntax
The syntax of a provider block is as follows:
provider "local_name" {
# Provider Specific Arguments
}
Here is the breakdown of the syntax:
provider
is the keyword to declare a provider block.
local_name
is the local name of the provider you want to use from the~/.terraform.d/plugins
folder (for Linux and Mac).
- block body (between
{}
) contains provider-specific arguments which have to be set in order to configure the provider.
For instance, if you wanted to use the AWS provider, your provider block would look like:
provider "aws" {
region = "us-west-2"
}
The above example provider block tells Terraform to use the AWS provider and configure it to work with resources in the "us-west-2" region.
Installing providers
Every provider must be installed before use in your Terraform configuration. You do this by using the
required_providers
block within the terraform block in your code. The required_providers block is used to define what providers your Terraform configuration requires. Terraform will download and install provider plugins that are specified by the required_providers block when you run terraform init. The installed plugins are cached locally in the ~/.terraform.d/plugins (for linux and mac) directory on your machine. This ensures that you have the required providers installed to run your Terraform configuration.
required_providers block contains three main pieces of information:
- Local Name
- Source
- Version
Local Name
In Terraform, a local name is the unique name that one gives to a provider inside a module. Outside of the required_providers block, Terraform configurations have to refer to providers by their local names. This means that anytime you might want to configure a provider or refer to it, you must use the local name given to it. Let's say you have a Terraform block configuration like this.
terraform {
required_version = ">= 1.3.7"
required_providers {
myplugin = {
version = ">= 2.7.0"
source = "mycorp/myplugin"
}
}
}
In the example above, myplugin is a local name given to the provider with the source mycorp/myplugin. When you run terraform init, Terraform will download the myplugin provider's binaries from mycorp/myplugin location in the Terraform public registry and store them in the myplugin folder under ~/.terraform.d/plugins folder. You would then use this local name to configure the provider to point the myplugin binary under ~/.terraform.d/plugins directory, like this:
provider "myplugin" {
# Provider Specific Arguments
}
If a resource does not have explicit mention of the provider by using the provider meta-argument, Terraform infers it automatically by the block type's first word and tries to match it with the local name of the provider configuration.
For example, you have an aws resource where you have not declared the provider explicitly.
provider "aws" {
region = "us-west-2"
}
provider "myplugin" {
key = "xhen7wh+u34"
}
resource "aws_instance" "example_ec2_instance" {
ami = "ami-0123456789"
instance_type = "t2.large"
tags = {
name = ""my-ec2-instance"
}
}
In this case, Terraform will automatically use the provider with a local name of aws because of the first word of the block type aws_instance, which matched the local name aws.
So, if you don't specify the provider meta-argument and use it to configure the resource, by default Terraform will look for a provider configuration whose local name matches the first word of the resource type. It is, therefore, important that each provider be given a unique and descriptive local name.
NOTE: Most providers have a preferred local name that they use as a prefix for all their resource types. For instance, resources of the hashicorp/aws provider are all prefaced with aws, such as aws_instance or aws_security_group. Therefore, you should use
aws
for AWS provider, google
for GCP provider, and azurerm
for AZURE provider as your local name.
Source
In Terraform, the "Source" is the location where Terraform downloads and installs the providers required for your infrastructure configuration. You would typically provide Terraform with an address or a URL from where it can download the provider binaries (executable files) you intend to use.
A source address consists of three parts, separated by slashes (
/
), in the following format:
[<HOSTNAME>/]<NAMESPACE>/<TYPE>
- HOSTNAME (Optional): The hostname is the "domain" or "platform" on which the provider is hosted. It is the location where the provider is stored. If you don't specify a hostname, Terraform will automatically search the provider in the registry.terraform.io (terraform public registry) by default.
- NAMESPACE: The namespace defines the logical grouping of providers. It is sort of like the main directory or folder inside HOSTNAME where it contains different providers. For example, hashicorp namespace contains all providers implemented by the HashiCorp organization, while the microsoft namespace contains all providers implemented by Microsoft.
- TYPE: The type is the actual name of the provider folder underneath the namespace, and it contains executable binaries. For Example: The hashicorp namespace contains providers like "aws", "google", "azure", etc.
Here is a simple example of how you might delegate a source address in a Terraform configuration:
terraform {
required_version = ">= 1.5.0"
required_providers {
myplugin = {
version = ">= 3.42.0"
source = "hashicorp/aws"
}
}
}
provider "aws" {
region = "us-west-2"
}
Here, when you will run terraform init, Terraform will download AWS binaries from AWS folder in HashiCorp namespace at registry.terraform.io and install them on your local machine at ~/.terraform.d/plugins/aws folder.
Version
In Terraform, each provider plugin has multiple releases on the registry, allowing the functionality of the provider to evolve over time. When using a provider dependency, a version constraint should be specified with the version argument for compatibility, so Terraform selects a single version of the provider that is compatible with all the modules.
Specifying a version constraint is optional, but highly recommended. If you don't specify one, Terraform will accept latest version of the provider as compatible, which can lead to issues.
For example, let's say we were using the AWS provider in our Terraform configuration and we wanted to specify that we should use a version of the provider compatible with the 3.x series or greater. We can specify a version constraint in the required_providers block.
terraform {
required_version = ">= 1.5.0"
required_providers {
myplugin = {
version = ">= 3.42.0"
source = "hashicorp/aws"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "example_ec2_instance" {
ami = "ami-0123456789"
instance_type = "t2.large"
tags = {
name = ""my-ec2-instance"
}
}
The version argument in the above example constraints the terraform to install aws provider greater than or equal to 3.0.0. We provide a constraint to ensure that our Terraform configuration is compatible with a certain range of provider versions to avoid unexpected behavior/errors due to provider version incompatibility. This will make our Terraform configuration more predictable and reliable.
Types of Provider
In Terraform, the providers are basically divided into two types: one is Default Providers, another is Non-Default Providers.
1. Default providers
A provider that does not have an alias meta-argument is known as a Default Provider. If you create a resource without specifying a provider explicitly with the provider meta-argument, Terraform will forward that resource to the default provider that matches the resource type. The match is done by the first word of the resource type.
For example, let's create an S3 bucket in AWS. Here we have specified two providers without an alias, the AWS provider and the GCP provider, and also the aws_s3_bucket resource doesn't specify which provider it should use explicitly. When you run terraform apply, Terraform will automatically use the AWS default provider because the first word of aws_s3_bucket is "aws".
provider "aws" {
region = "us-east-1"
}
provider "google" {
project = "my-project-id"
region = "us-east-1"
}
resource "aws_s3_bucket" "bucket" {
bucket = "my-bucket"
acl = "private"
}
In this example, the Data Resource my_bucket_data depends upon the id attribute from the managed resource my_bucket. Terraform will delay the reading of my_bucket_data until my_bucket has been created and its id attribute is available.
2. Non-default providers
Meta-arguments of Provider
In Terraform, meta-arguments are special arguments that can be used with providers to customize their behavior. The following meta-arguments are available for use with Terraform providers:
1. alias
The alias argument in Terraform allows to provide more than one non-default configuration of the provider. This will take care of the scenarios when you want to use the same provider for different things, like using AWS in both the US East and US West regions.
To manage more than one non-default configuration, multiple provider blocks of the same local name must be defined but with different configurations. Additional configurations beyond the default require an alias meta-argument for naming them uniquely. The provider block missing the alias argument is considered the default configuration for that provider.
For example, let's say that you want to use AWS provider in two different regions: US East and US West. You define two separate provider configurations:
provider "aws" {
region = "us-east-1"
}
provider "aws" {
alias = "west-region"
region = "us-west-2"
}
In the above example, we have two configurations for the AWS provider. The first one is the default configuration since it does not have an alias argument, using the us-east-1 region. The second configuration will be an additional configuration with the alias being west-region using the us-west-2 region.
By default, if you don't specify the provider meta-argument, Terraform will try to look for a default provider configuration that exactly matches the first word of the resource type. In order to utilize an provider configuration which is not the default, you will need to set the provider meta-argument to a
<PROVIDER_NAME>.<ALIAS>
reference.
For example, to provision an instance in the west region on AWS you would use:
resource "aws_instance" "instance" {
provider = aws.west-region
ami = "ami-0123456789"
instance_type = "t2.micro"
tags = {
name = "instance"
}
}
In the above example, aws_instance resource will use west-region non-default provider configuration to create an instance in us-west-2 region.
2. Version (Deprecated)
The version meta-argument is a legacy method of specifying a version constraint for a provider in a Terraform configuration. It is similar to the version argument in a required_providers block. A version constraint in a provider configuration was used only if no version constraint for the provider was defined in the required_providers block. The version meta-argument in provider configurations is deprecated and has no effect. Terraform will drop this feature in the next major version.
Dependency Lock File
When you set up Terraform, it requires you to define, in your configuration file, rules called "version constraints" that specify which versions of each dependency, such as plugins and modules, are compatible with your project. Using those rules, Terraform will download and install the correct version of such dependencies onto your local machine.
Once Terraform has selected particular versions of dependencies, it will remember those choices in a special file called a dependency lock file. This file keeps track of exactly what versions of dependencies were selected so that Terraform can use the same dependencies again in the future, avoiding the use of different versions of dependencies. The dependency lock file acts like a snapshot of the dependencies that will be used at any given time. By locking to these particular versions, Terraform can guarantee consistency and reproducibility for your project and avoid surprising changes or conflicts that might come with using different versions of those dependencies.
The name of the lock file is always
.terraform.lock.hcl
, and it is located in your working directory, the same directory where the .tf
files for the root module of your configuration are kept. Its name, .terraform.lock.hcl, suggests it is a lock file for many things Terraform caches in the .terraform
subdirectory in your working directory.
If Terraform modifies the lock file in any way, it will indicate that to you with a message like this:
Terraform has made some changes to the provider dependency selections recordedin the .terraform.lock.hcl
file. Review those changes and commit them to your version control system if they represent changes you
intended to make.
Example: Installing the 3.2.2 Version of the Null Provider
terraform {
required_version = ">= 1.5.0"
required_providers {
null = {
version = "3.2.2"
source = "hashicorp/null"
}
}
}
provider "null" {
}
In the above example, the version constraint requires that the null provider be of version 3.2.2. When you run terraform init for the first time, Terraform selects a particular version of the Null provider that meets the version constraint and creates a dependency lock file (.terraform.lock.hcl) that records this selection. The lock file includes the exact version of the null provider, including its hashes.
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/null" {
version = "3.2.2"
hashes = [
"h1:vWAsYRd7MjYr3adj8BVKRohVfHpWQdvkIwUQ2Jf5FVM="
"zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7"
"zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a"
"zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3"
"zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606"
"zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546"
"zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539"
"zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452"
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3"
"zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422"
"zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae"
"zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1"
"zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e"
]
}
If you try to rerunning terraform init again with the null provider version changed to something else, say 2.1.0. This time Terraform will fail so that it keeps your project consistent and reproducible since the lock file was a snapshot of what your project dependencies used at that point in time, and Terraform will use only the exact versions of dependencies recorded in the lock file.
In this case, Terraform will emit an error message such as:
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/null from the dependency lock file
Error: Failed to query available provider packages
Could not retrieve the list of available versions for
provider hashicorp/null: locked provider
registry.terraform.io/hashicorp/null 3.2.2 does not match
configured version constraint 2.1.0; must use terraform init -upgrade to allow selection of new versions
This error message indicates that Terraform is blocking your attempt to use a different version of the null provider, which is important for the reproducibility of a project.
Updating a existing version in lock file
The following is the command you can use to update the existing version of a provider in the lock file.
terraform init --upgrade
The
--upgrade
option here will instruct Terraform to disregard the existing version selection in the lock file and instead select the newest available version which meets the version constraint in your Terraform configuration.
Related Pages
Feedback
Was this page helpful?