Terraform Providers Connecting to Cloud Platforms

Terraform itself does not know how to create an AWS server or an Azure database. It relies on plugins called providers to do that work. This topic explains what providers are, how they work, where they come from, and how to configure them correctly.

What Is a Provider

A provider is a plugin that teaches Terraform how to communicate with a specific service or platform. Each provider contains the code needed to talk to a service's API.

Analogy: The Universal Remote Control

Imagine Terraform as a universal remote control. On its own, the remote does nothing. You insert a module (provider) for your TV, and now the remote controls your TV. Insert a different module for your air conditioner, and now it controls that too. Providers are those modules.

Diagram: Provider Role

Your .tf files
      |
      v
[ Terraform Core ]
      |
      |---> [ AWS Provider ]  ---> AWS API  ---> EC2, S3, RDS...
      |---> [ Azure Provider ] --> Azure API --> VMs, Blobs...
      |---> [ GitHub Provider ] -> GitHub API -> Repos, Teams...
      |---> [ Cloudflare Provider ] -> Cloudflare API -> DNS, CDN...

Where Providers Come From

Providers are published on the Terraform Registry at registry.terraform.io. The registry has three tiers:

TierWho Maintains ItExample
OfficialHashiCorphashicorp/aws, hashicorp/azurerm
PartnerTechnology partners (verified)datadog/datadog, mongodb/mongodbatlas
CommunityIndividual contributorsVarious open-source providers

When you run terraform init, Terraform downloads the provider plugins you declared and stores them in the .terraform folder.

Declaring a Provider

You declare providers in a terraform block and configure them in a provider block.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

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

Understanding Version Constraints

The version argument controls which provider version Terraform downloads. Version constraints follow standard rules:

ConstraintMeaning
= 5.0.0Exactly version 5.0.0 only
>= 5.0Version 5.0 or newer
~> 5.0Any version from 5.0 up to but not including 6.0 (patch updates only)
~> 5.31Any version from 5.31 up to but not including 5.32

The ~> (tilde-greater-than) operator is called the pessimistic constraint operator. Most teams use it because it allows bug fixes but prevents breaking changes from a major version upgrade.

Provider Authentication

Every provider needs credentials to talk to its service. Terraform never stores passwords directly in your .tf files — that would be a serious security risk. Instead, providers read credentials from safe locations.

AWS Authentication Options

  • Environment variables: Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY before running Terraform
  • AWS credentials file: Stored at ~/.aws/credentials on your machine
  • IAM roles: Automatically used when running Terraform on an EC2 instance or in a CI/CD pipeline with an attached role

Example: Setting AWS Credentials via Environment Variables

export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="us-east-1"

With these environment variables set, the AWS provider automatically picks them up — no credentials in your code.

Configuring Multiple Providers

A single Terraform project can use multiple providers at once. You might deploy servers on AWS while managing DNS on Cloudflare.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "~> 4.0"
    }
  }
}

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

provider "cloudflare" {
  api_token = var.cloudflare_api_token
}

Provider Aliases for Multiple Regions

Sometimes you need to create resources in two different regions using the same provider. Use the alias argument to create two instances of the same provider.

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

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

resource "aws_instance" "east_server" {
  # uses the default aws provider (us-east-1)
  ami           = "ami-0abc123"
  instance_type = "t3.micro"
}

resource "aws_instance" "west_server" {
  provider      = aws.west   # explicitly uses the west alias
  ami           = "ami-0xyz789"
  instance_type = "t3.micro"
}

Key Points

  • A provider is a plugin that enables Terraform to communicate with a specific service's API.
  • Declare providers in the required_providers block with a source and version constraint.
  • Use ~> version constraints to allow safe patch-level updates without breaking changes.
  • Never hard-code credentials in .tf files — use environment variables, credentials files, or IAM roles.
  • Use provider aliases to manage resources across multiple regions or accounts with the same provider.

Leave a Comment