Terraform
Configure Terraform providers
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.
Prerequisites
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:
- Terraform v1.2+ installed locally.
- An AWS account with IAM credentials to use with this tutorial.
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 example repository
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
Install a provider from the registry
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:
- Documentation for all resources and data sources supported by the provider.
- Guides for authentication, upgrading your provider, and other use cases.
- A Use Provider button with example configuration you can copy into your workspace.
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:
- source: The provider's address in the registry. The format is
[hostname/]namespace/type
. When no hostname is specified, Terraform defaults toregistry.terraform.io
. - version: A version constraint that determines which provider versions are
acceptable. A
~> 6.3.0
constraint allows any version in the 6.3.x series but prevents updates to 6.4 and later.
Version constraints
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.2
Initialize 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.
Configure your provider
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-"
}
Authenticate your provider
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:
- Parameters in the provider configuration
- Environment variables (recommended for local development)
- Shared credentials files
- Shared configuration files
- Container credentials
- Instance profile credentials and region
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.
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 configuration
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.
Upgrade a provider
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 file
Examine 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:
- The exact version of the provider that was selected (
6.3.0
) - The version constraint from your configuration (
~> 6.3.0
) - Cryptographic hashes to verify provider authenticity
Upgrade to a newer version
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.
Use a child module
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.
Provider aliasing
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.
Clean up your infrastructure
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.
Next steps
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:
- Read the provider configuration documentation.
- Learn about provider development
- Explore provider-specific tutorials for AWS, Azure, Google Cloud, and other platforms.
- Review the dependency lock file documentation for advanced version management.