What Is a Terraform Provider?
A Terraform provider is a plugin that lets Terraform talk to an API. Every resource you manage — EC2 instances, DNS records, Kubernetes deployments, GitHub repos — requires a provider.
Providers translate your HCL configuration into API calls:
your .tf file → Terraform Core → Provider Plugin → API → Cloud Resource
The Terraform Registry hosts 4,000+ providers. The most common: AWS, Azure, GCP, Kubernetes, Docker, GitHub, Cloudflare, Datadog.
Declaring Providers: required_providers
Every Terraform project should declare its providers in a required_providers block:
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = ">= 2.20"
}
}
}
Version Constraints
| Constraint | Meaning | Example |
|---|---|---|
= 5.0.0 | Exact version | Only 5.0.0 |
>= 5.0 | Minimum version | 5.0 or higher |
~> 5.0 | Pessimistic constraint | >= 5.0, < 6.0 |
~> 5.0.1 | Patch-level constraint | >= 5.0.1, < 5.1.0 |
>= 5.0, < 5.50 | Range | Between 5.0 and 5.49.x |
Best practice: Use ~> MAJOR.MINOR for production — allows patch updates but blocks breaking changes.
Configuring Providers
AWS Provider
provider "aws" {
region = "us-east-1"
profile = "production"
default_tags {
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}
}
Authentication order (AWS provider checks these in sequence):
access_key/secret_keyin provider block (not recommended)- Environment variables:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY - Shared credentials file (
~/.aws/credentials) - IAM instance profile (EC2/ECS)
- AWS SSO /
aws sso login
Azure Provider
provider "azurerm" {
features {}
subscription_id = var.subscription_id
tenant_id = var.tenant_id
}
Authentication: Service Principal, Managed Identity, or Azure CLI (az login).
Google Cloud Provider
provider "google" {
project = "my-project-id"
region = "us-central1"
zone = "us-central1-a"
}
Authentication: GOOGLE_CREDENTIALS environment variable, Application Default Credentials (gcloud auth application-default login), or service account key file.
Kubernetes Provider
provider "kubernetes" {
config_path = "~/.kube/config"
config_context = "my-cluster"
}
# Or connect to EKS directly
provider "kubernetes" {
host = data.aws_eks_cluster.main.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.main.certificate_authority[0].data)
token = data.aws_eks_cluster_auth.main.token
}
Provider Aliases: Multiple Regions or Accounts
Use alias when you need multiple configurations of the same provider:
# Default AWS provider — us-east-1
provider "aws" {
region = "us-east-1"
}
# Second AWS provider — eu-west-1
provider "aws" {
alias = "europe"
region = "eu-west-1"
}
# Use the alias in resources
resource "aws_instance" "us_server" {
ami = "ami-12345678"
instance_type = "t3.micro"
# Uses default provider (us-east-1)
}
resource "aws_instance" "eu_server" {
provider = aws.europe
ami = "ami-87654321"
instance_type = "t3.micro"
# Uses aliased provider (eu-west-1)
}
Multi-Account Pattern
provider "aws" {
alias = "production"
region = "us-east-1"
profile = "prod-account"
}
provider "aws" {
alias = "staging"
region = "us-east-1"
profile = "staging-account"
}
# Pass providers to modules
module "vpc" {
source = "./modules/vpc"
providers = {
aws = aws.production
}
}
How Provider Installation Works
When you run terraform init:
- Terraform reads
required_providers - Downloads providers from the registry (or a mirror)
- Stores them in
.terraform/providers/ - Records exact versions in
.terraform.lock.hcl
$ terraform init
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.82.2...
- Installed hashicorp/aws v5.82.2 (signed by HashiCorp)
The Lock File
.terraform.lock.hcl pins exact provider versions and checksums:
provider "registry.terraform.io/hashicorp/aws" {
version = "5.82.2"
constraints = "~> 5.0"
hashes = [
"h1:abc123...",
"zh:def456...",
]
}
Always commit .terraform.lock.hcl to version control. This ensures everyone on your team uses the same provider version.
Provider Tiers
| Tier | Maintained By | Examples |
|---|---|---|
| Official | HashiCorp | AWS, Azure, GCP, Kubernetes |
| Partner | Technology company | Cloudflare, Datadog, MongoDB |
| Community | Individual contributors | Thousands of niche providers |
Official and Partner providers are generally more reliable and better documented.
Common Providers and Their Uses
| Provider | Source | Use Case |
|---|---|---|
hashicorp/aws | AWS resources | EC2, S3, RDS, Lambda, VPC |
hashicorp/azurerm | Azure resources | VMs, Storage, AKS, Functions |
hashicorp/google | GCP resources | Compute, GKE, Cloud SQL |
hashicorp/kubernetes | K8s resources | Deployments, Services, ConfigMaps |
hashicorp/helm | Helm charts | Deploy Helm charts via Terraform |
hashicorp/docker | Docker | Containers, images, networks |
hashicorp/vault | Secrets | Manage HashiCorp Vault |
hashicorp/github | GitHub | Repos, teams, branch protection |
cloudflare/cloudflare | Cloudflare | DNS, WAF, Workers |
hashicorp/random | Utilities | Random passwords, IDs, shuffles |
hashicorp/null | Utilities | Triggers, provisioners |
Data Sources vs Resources
Providers expose two types:
- Resources: Create and manage infrastructure (
resource "aws_instance") - Data sources: Read existing infrastructure (
data "aws_ami")
# Data source — read-only, doesn't create anything
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"]
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
}
# Resource — creates an EC2 instance
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
}
Troubleshooting
“Failed to install providers”
Error: Failed to install provider
Could not retrieve the list of available versions for provider hashicorp/aws
Causes: No internet access, corporate firewall, or registry outage. Fix with a filesystem mirror or network mirror.
“Inconsistent dependency lock file”
Run terraform init -upgrade to update the lock file, or delete .terraform.lock.hcl and re-init.
Provider version conflict
Error: Failed to query available provider packages
Could not retrieve the list of available versions: no available releases match the given constraints
Check your version constraint — it may be too restrictive. Use terraform providers to see current requirements.
Duplicate provider configuration
Error: Duplicate provider configuration
You declared the same provider twice without using alias. Add alias = "name" to the second declaration.
Best Practices
- Pin versions: Always use
required_providerswith version constraints - Commit lock file:
.terraform.lock.hclbelongs in version control - Don’t hardcode credentials: Use environment variables, IAM roles, or vault
- Use aliases for multi-region/account: Not separate Terraform projects
- Check the registry: Read provider docs before writing resources
- Update regularly: Run
terraform init -upgradeperiodically to get security fixes
Hands-On Courses
Learn by doing with interactive courses on CopyPasteLearn:
Conclusion
Terraform providers are the interface between your configuration and real infrastructure. Declare them in required_providers, pin versions with ~>, authenticate securely (never hardcode keys), use aliases for multi-region deployments, and always commit your lock file. The Terraform Registry is the starting point for finding providers for any service you need to manage.




