Skip to main content

Providers

Providers are plugins that enable Terraform to interact with cloud platforms, SaaS providers, and other APIs. Each provider adds a set of resource types and data sources that Terraform can manage.

Provider Configuration

Provider blocks configure the named provider:
provider "<PROVIDER_NAME>" {
  # Configuration options
}

Example

provider "aws" {
  region = "us-west-2"
  
  default_tags {
    tags = {
      Environment = "production"
      ManagedBy   = "Terraform"
    }
  }
}

Provider Requirements

Declare required providers in a terraform block:
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    
    random = {
      source  = "hashicorp/random"
      version = "~> 3.0"
    }
  }
}

Source Addresses

Provider source addresses have the format:
<HOSTNAME>/<NAMESPACE>/<TYPE>
Examples:
  • hashicorp/aws - Official AWS provider
  • terraform-providers/azurerm - Azure provider
  • example.com/custom/provider - Third-party provider
The hostname defaults to registry.terraform.io if omitted.

Version Constraints

Specify acceptable provider versions:
version = "~> 5.0"      # >= 5.0, < 6.0
version = ">= 5.0"      # 5.0 or higher
version = ">= 5.0, < 6.0" # Between 5.0 and 6.0
version = "= 5.1.0"     # Exactly 5.1.0

Multiple Provider Configurations

Use aliases for multiple configurations of the same provider:
provider "aws" {
  region = "us-west-2"
}

provider "aws" {
  alias  = "east"
  region = "us-east-1"
}

provider "aws" {
  alias  = "europe"
  region = "eu-west-1"
}

Using Aliased Providers

Reference aliased providers in resources:
resource "aws_instance" "west" {
  provider = aws
  
  ami           = "ami-12345678"
  instance_type = "t2.micro"
}

resource "aws_instance" "east" {
  provider = aws.east
  
  ami           = "ami-87654321"
  instance_type = "t2.micro"
}

Provider Configuration Reference

Resources can reference provider configurations:
variable "aws_region" {
  type = string
}

provider "aws" {
  region = var.aws_region
}
Provider configurations cannot use resource outputs. Providers are configured before resources are created.

Default Provider Configuration

Terraform uses the default (unaliased) provider configuration when:
  • No provider argument is specified in a resource
  • The resource type matches the provider name
provider "aws" {
  region = "us-west-2"
}

# Uses the default aws provider
resource "aws_instance" "web" {
  ami = "ami-12345678"
}

Provider Configuration in Modules

Modules can declare which provider configurations they accept:

Child Module

# modules/web-app/main.tf
terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

resource "aws_instance" "app" {
  ami = var.ami_id
}

Root Module

provider "aws" {
  region = "us-west-2"
}

provider "aws" {
  alias  = "east"
  region = "us-east-1"
}

module "web_app_west" {
  source = "./modules/web-app"
  
  providers = {
    aws = aws
  }
}

module "web_app_east" {
  source = "./modules/web-app"
  
  providers = {
    aws = aws.east
  }
}

Provider Metadata

Access provider metadata in resources:
resource "aws_instance" "web" {
  ami = "ami-12345678"
  
  tags = {
    Provider = "aws"
  }
}

Provider Functions

Some providers offer built-in functions:
# Using a provider-contributed function
locals {
  encoded = provider::aws::encode_secret(var.password)
}
Provider functions are namespaced under provider::<PROVIDER>::<FUNCTION>.

Provider Configuration Files

Organize provider configurations:
# providers.tf
provider "aws" {
  region = var.aws_region
}

provider "random" {}

provider "tls" {}

Authentication

Providers support various authentication methods:

Static Credentials

provider "aws" {
  access_key = "AKIAIOSFODNN7EXAMPLE"
  secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
  region     = "us-west-2"
}
Never commit credentials to version control. Use environment variables or credential files instead.

Environment Variables

export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="us-west-2"
provider "aws" {
  # Credentials from environment variables
}

Credential Files

provider "aws" {
  shared_credentials_files = ["~/.aws/credentials"]
  profile                  = "production"
}

Provider Validation

Providers validate their configuration during terraform init:
terraform init
Common validation errors:
  • Invalid region names
  • Missing required configuration
  • Unsupported provider versions

Provider Development

The provider implementation defines:
  • Resource types
  • Data source types
  • Configuration schema
  • Authentication logic
From the source code (internal/configs/provider.go:20-52):
type Provider struct {
    Name       string
    NameRange  hcl.Range
    Alias      string
    AliasRange *hcl.Range
    
    Version VersionConstraint
    Config  hcl.Body
    
    DeclRange hcl.Range
}

Provider Naming

Provider names must be normalized and valid:
provider "aws" { }        # Valid
provider "aws-custom" { } # Valid
provider "AWS" { }        # Invalid - must be lowercase
provider "2nd-aws" { }    # Invalid - cannot start with digit
From internal/configs/provider.go:286-312, provider names are validated to ensure they conform to the naming standards.

Deprecated Provider Version Constraints

Provider version constraints inside provider blocks are deprecated. Use required_providers instead:Deprecated:
provider "aws" {
  version = "~> 5.0"
}
Recommended:
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

Provider Installation

Terraform downloads providers during initialization:
terraform init
Providers are installed to:
  • .terraform/providers/ (local cache)
  • ~/.terraform.d/plugins/ (global cache)

Provider Mirroring

Use a local mirror for air-gapped environments:
provider_installation {
  filesystem_mirror {
    path    = "/usr/local/share/terraform/providers"
    include = ["example.com/*/*"]
  }
  
  direct {
    exclude = ["example.com/*/*"]
  }
}

Best Practices

Pin Versions

Always specify provider version constraints to ensure consistent behavior.

Separate Files

Keep provider configurations in providers.tf for clarity.

Use Variables

Parameterize provider configurations for flexibility across environments.

Secure Credentials

Never hardcode credentials. Use environment variables or credential files.

Common Provider Blocks

AWS

provider "aws" {
  region  = "us-west-2"
  profile = "production"
  
  assume_role {
    role_arn = "arn:aws:iam::123456789012:role/TerraformRole"
  }
}

Azure

provider "azurerm" {
  features {}
  
  subscription_id = var.subscription_id
  tenant_id       = var.tenant_id
}

Google Cloud

provider "google" {
  project = var.project_id
  region  = "us-central1"
  zone    = "us-central1-a"
}

Next Steps

Resources

Use providers to create resources

Modules

Pass providers to child modules

Build docs developers (and LLMs) love