Terraform providers are plugins that enable Terraform to interact with cloud platforms, SaaS providers, and other APIs. Terraform sources providers from the Terraform registry by default, which hosts providers maintained by HashiCorp, our partners, and community members. Each provider supports a set of resource types and data sources that you can manage with Terraform.
To use Terraform to manage resources for your chosen cloud platform, you must first install the corresponding provider and configure authentication. With the provider installed, you can use Terraform to create and manage the resources it supports.
In this tutorial, you will learn how to source and version providers from the Terraform registry, configure and authenticate providers, and upgrade provider versions safely. You will also learn how to configure multiple instances of the same provider using aliases and control which providers your Terraform modules use to provision infrastructure.
This tutorial assumes that you are familiar with the Terraform workflow. If you are new to Terraform, complete the Get Started collection first.
You can complete this tutorial using AWS, Azure, or Google Cloud Platform. Select the tab at the top of the page for your preferred cloud provider.
To complete this tutorial, you will need:
Note
Some of the infrastructure in this tutorial may not qualify for your cloud service's free tier. Destroy the infrastructure at the end of the tutorial to avoid unnecessary charges. We are not responsible for any charges that you incur.
Clone the example repository for this tutorial, which contains example Terraform configuration for you to use.
$ git clone https://github.com/hashicorp-education/learn-terraform-providers
Change to the repository directory for your preferred cloud vendor.
$ cd learn-terraform-providers/aws
The Terraform registry hosts publicly available Terraform providers and modules. Before adding a provider to your configuration, review the provider documentation on the registry to understand the provider's capabilities and requirements.
Visit the AWS provider page in the Terraform registry.
The provider documentation includes:
Terraform providers are distributed as plugins that Terraform downloads and installs when you initialize your workspace. You can specify which providers your configuration requires in the required_providers
block within the terraform
configuration block.
Review the example configuration in terraform.tf
.
terraform.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.3.0"
}
}
required_version = ">= 1.2"
}
The required_providers
block specifies:
[hostname/]namespace/type
. When no hostname is specified, Terraform defaults to registry.terraform.io
.~> 6.3.0
constraint allows any version in the 6.3.x series but prevents updates to 6.4 and later.Terraform supports several version constraint operators:
>= 6.0
: Version 6.0 or newer~> 6.0
: Any version in the 6.x series (equivalent to >= 6.0, < 7.0
)~> 6.3.0
: Any version in the 6.3.x series (equivalent to >= 6.3.0, < 6.4.0
)= 6.4.2
: Exactly version 6.4.2Initialize your configuration to download the specified providers.
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 6.3.0"...
- Installing hashicorp/aws v6.3.0...
- Installed hashicorp/aws v6.3.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Terraform downloaded the providers and created a dependency lock file for your workspace. The dependency lock file tracks the version and checksums of the providers used by your configuration. Terraform will use the versions specified in your dependency lock file until you explicitly upgrade them with the terraform init -upgrade
command.
A provider
block configures the named provider. Most providers allow you to configure their behavior in the provider block, such as endpoint URLs, cloud regions, or other settings that apply to all resources managed by that provider. If you do not specify a provider block for a given resource, Terraform will default to a provider with empty configuration. To make your configuration easier to understand, we recommend explicitly including a provider block for each provider used by your configuration, even if it is empty.
Review the provider
block in your configuration:
main.tf
provider "aws" {
region = "us-west-2"
}
This provider block configures the AWS provider to create resources in the us-west-2
region.
Add a default_tags
block to your AWS provider block:
main.tf
provider "aws" {
region = "us-west-2"
default_tags {
tags = {
Environment = "tutorial"
Project = "terraform-configure-providers"
}
}
}
The default_tags
configuration block for the AWS provider automatically applies tags to all resources managed by the provider that support tagging.
The rest of the configuration in main.tf
defines an AWS s3 bucket.
main.tf
resource "aws_s3_bucket" "example" {
bucket_prefix = "terraform-provider-example-"
}
Terraform providers need credentials to authenticate with cloud APIs. Each provider supports different authentication methods, which are documented in the provider's registry page.
The AWS provider supports several authentication methods:
Warning
We do not recommend setting your provider's credentials as parameters in your provider configuration. Provider credentials are generally considered sensitive values, and including them in your configuration files could expose them to potential attackers if you share your configuration in a Version Control System (VCS).
For this tutorial, authenticate either using the AWS CLI or by setting environment variables with an access key ID and secret:
Authenticate using the AWS CLI:
$ aws configure
AWS Access Key ID [None]: your-access-key-id
AWS Secret Access Key [None]: your-secret-access-key
Default region name [None]:
Default output format [None]:
You can leave the default region name and output format blank.
Set AWS environment variables with an access key ID and secret:
$ export AWS_ACCESS_KEY_ID="your-access-key-id"
$ export AWS_SECRET_ACCESS_KEY="your-secret-access-key"
Verify that your credentials are correctly configured by planning your configuration:
$ terraform plan
Terraform used the selected providers to generate the following execution plan. Resource
actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_s3_bucket.example will be created
+ resource "aws_s3_bucket" "example" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
## ...
Plan: 1 to add, 0 to change, 0 to destroy.
─────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take
exactly these actions if you run "terraform apply" now.
Apply your configuration to create your resources. Respond to the confirmation prompt with a yes
.
$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource
actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_s3_bucket.example will be created
+ resource "aws_s3_bucket" "example" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
## ...
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_s3_bucket.example: Creating...
aws_s3_bucket.example: Creation complete after 2s [id=terraform-provider-example-20250729193943685700000001]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Providers are maintained and versioned separately from Terraform itself, and provider developers periodically release new versions that include bug fixes, new features, and additional resources. Terraform's dependency lock file ensures that your team uses consistent provider versions until you explicitly decide to upgrade your provider.
Review the dependency lock fileExamine the generated lock file:
$ cat .terraform.lock.hcl
.terraform.lock.hcl
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/aws" {
version = "6.3.0"
constraints = "~> 6.3.0"
hashes = [
"h1:p8RNhYsu0ewxz13m4nNmc/gXB9tfn9b3d2KKdj91T5g=",
"zh:0502dc1889cca94c89bfc00b214970bffa2d81a2cdb55e05ab6192484ddb1532",
## ...
"zh:eb8db004ccbf52b3ed8b15189c59560c233abd2c2f5ac5ee68768841c3c8e206",
]
}
The lock file records:
6.3.0
)~> 6.3.0
)To upgrade to a newer provider version, update your configured version constraint, and use the terraform init -upgrade
command.
First, edit terraform.tf
to update the version constraint for your provider.
terraform.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.6.0"
}
}
required_version = ">= 1.2"
}
Next, run terraform init -upgrade
to upgrade your configuration's providers to the latest version that matches their configured version constraint.
$ terraform init -upgrade
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 6.6.0"...
- Installing hashicorp/aws v6.6.0...
- Installed hashicorp/aws v6.6.0 (signed by HashiCorp)
Terraform has made some changes to the provider dependency selections recorded
in the .terraform.lock.hcl file. Review those changes and commit them to your
version control system if they represent changes you intended to make.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
The -upgrade
flag tells Terraform to upgrade your workspace’s providers to the latest version that matches the configured version constraint, and update the lock file.
Note
Review provider release notes before upgrading, especially for major version changes that might include breaking changes or require configuration updates.
When you use modules, Terraform automatically passes the provider configuration from the root module to child modules. This allows child modules to create resources using the same provider settings.
Add the following module block in main.tf
, to use the terraform-aws-modules/s3-bucket/aws module
to manage an S3 bucket:
main.tf
module "website" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "~> 5.2.0"
bucket_prefix = "terraform-provider-website-"
tags = {
Module = "s3-bucket"
}
}
Initialize your workspace to install the new module.
$ terraform init
Initializing the backend...
Initializing modules...
Downloading registry.terraform.io/terraform-aws-modules/s3-bucket/aws 5.2.0 for s3_bucket...
- s3_bucket in .terraform/modules/website
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v6.6.0
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Apply your configuration.
$ terraform apply
module.website.data.aws_caller_identity.current: Reading...
module.website.data.aws_partition.current: Reading...
module.website.data.aws_region.current: Reading...
module.website.data.aws_partition.current: Read complete after 0s [id=aws]
module.website.data.aws_region.current: Read complete after 0s [id=us-west-2]
aws_s3_bucket.example: Refreshing state... [id=terraform-provider-example-20250729151130230100000001]
module.website.data.aws_caller_identity.current: Read complete after 0s [id=949008909725]
Terraform used the selected providers to generate the following execution plan. Resource
actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.website.aws_s3_bucket.this[0] will be created
+ resource "aws_s3_bucket" "this" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
## ...
Plan: 2 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
module.website.aws_s3_bucket.this[0]: Creating...
module.website.aws_s3_bucket.this[0]: Creation complete after 3s [id=terraform-provider-website-20250729154634013600000001]
module.website.aws_s3_bucket_public_access_block.this[0]: Creating...
module.website.aws_s3_bucket_public_access_block.this[0]: Creation complete after 1s [id=terraform-provider-website-20250729154634013600000001]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
The child module will automatically use the same default provider configuration as your root module.
Sometimes you need multiple configurations of the same provider in your workspace. For example, you might want to create resources in multiple regions or use different authentication credentials. Provider aliases allow you to define multiple configurations of the same provider. When you define a provider with the alias
argument set, you can add the provider
meta-argument and specify your alternative provider configuration in resources, data sources, or modules.
If you do not define a default provider block (without an alias
argument), then Terraform will automatically generate a default provider configuration for resources that use that provider. We recommend that you include explicit provider blocks for every provider you define, to make your configuration easier to understand.
Add a second AWS provider configuration for the us-east-1
region:
main.tf
provider "aws" {
alias = "east"
region = "us-east-1"
default_tags {
tags = {
Environment = "tutorial"
Project = "terraform-configure-providers"
}
}
}
module "website_east" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "5.2.0"
providers = {
aws = aws.east
}
bucket_prefix = "example-east-"
}
The alias
argument to the provider block creates a named variant of that provider. Modules use the providers
argument to map provider aliases to their internal provider requirements. Resources, data sources, and modules without an explicit provider
argument use the default (non-aliased) provider. All provider blocks will use the same version of the given provider.
Re-run terraform init
to install the new module. Terraform installs each instance of a module in its own directory in your local workspace, since each instance of the module can be a different version.
$ terraform init
Initializing the backend...
Initializing modules...
Downloading registry.terraform.io/terraform-aws-modules/s3-bucket/aws 5.2.0 for website_east...
- website_east in .terraform/modules/website_east
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v6.6.0
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Apply the configuration to create resources in both regions. Respond to the confirmation prompt with a yes
.
$ terraform apply
module.website.data.aws_partition.current: Reading...
module.website.data.aws_region.current: Reading...
module.website.data.aws_caller_identity.current: Reading...
module.website.data.aws_partition.current: Read complete after 0s [id=aws]
module.website.data.aws_region.current: Read complete after 0s [id=us-west-2]
aws_s3_bucket.example: Refreshing state... [id=terraform-provider-example-20250729151130230100000001]
## ...
Plan: 2 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
module.website_east.aws_s3_bucket.this[0]: Creating...
module.website_east.aws_s3_bucket.this[0]: Creation complete after 3s [id=terraform-provider-website-east-20250729164521300100000001]
module.website_east.aws_s3_bucket_public_access_block.this[0]: Creating...
module.website_east.aws_s3_bucket_public_access_block.this[0]: Creation complete after 1s [id=terraform-provider-website-east-20250729164521300100000001]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Per-resource region override with the AWS provider
The AWS provider supports overriding the region on a per-resource basis without creating a separate provider alias. This is useful for resources that must be created in specific regions, such as CloudFront distributions or Route 53 hosted zones.
Add an S3 bucket that explicitly sets its region:
main.tf
resource "aws_s3_bucket" "cloudfront_logs" {
region = "us-west-1"
bucket_prefix = "terraform-cloudfront-logs-"
}
This approach gives you flexibility to place specific resources in different regions without creating multiple provider configurations for every region you might need.
Apply your configuration to create the new bucket in us-west-1
using your default AWS provider.
$ terraform apply
module.website_east.data.aws_region.current: Reading...
module.website_east.data.aws_caller_identity.current: Reading...
module.website_east.data.aws_partition.current: Reading...
module.website_east.data.aws_partition.current: Read complete after 0s [id=aws]
## ...
Terraform used the selected providers to generate the following execution plan. Resource
actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_s3_bucket.cloudfront_logs will be created
+ resource "aws_s3_bucket" "cloudfront_logs" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
## ...
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_s3_bucket.cloudfront_logs: Creating...
aws_s3_bucket.cloudfront_logs: Creation complete after 3s [id=terraform-cloudfront-logs-20250729164952700100000001]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Remove the infrastructure you created in this tutorial to avoid unnecessary charges.
Run terraform destroy
to remove your infrastructure. Respond to the confirmation prompt with "yes".
$ terraform destroy
module.website.data.aws_partition.current: Reading...
module.website.data.aws_region.current: Reading...
module.website.data.aws_caller_identity.current: Reading...
## ...
Terraform used the selected providers to generate the following execution plan. Resource
actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# aws_s3_bucket.cloudfront_logs will be destroyed
- resource "aws_s3_bucket" "cloudfront_logs" {
- arn = "arn:aws:s3:::terraform-cloudfront-logs-20250729164952700100000001" -> null
- bucket = "terraform-cloudfront-logs-20250729164952700100000001" -> null
## ...
Plan: 0 to add, 0 to change, 6 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
module.website_east.aws_s3_bucket_public_access_block.this[0]: Destroying... [id=terraform-provider-website-east-20250729164521300100000001]
module.website.aws_s3_bucket_public_access_block.this[0]: Destroying... [id=terraform-provider-website-20250729164458770100000001]
## ...
aws_s3_bucket.cloudfront_logs: Destruction complete after 1s
aws_s3_bucket.example: Destruction complete after 1s
module.website.aws_s3_bucket.this[0]: Destruction complete after 0s
Destroy complete! Resources: 6 destroyed.
In this tutorial, you learned how to manage Terraform providers in your configuration. You explored the Terraform registry, configured and versioned providers, handled authentication, used provider inheritance in modules, and implemented provider aliases for multi-region deployments.
To continue learning about Terraform providers:
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4