Skip to main content

Command Palette

Search for a command to run...

Day 3: Understanding Providers & AWS Setup

Updated
β€’8 min read
Day 3: Understanding Providers & AWS Setup
S

I'm a cloud-native enthusiast and tech blogger, sharing insights on Kubernetes, AWS, CI/CD, and Linux across my blog and Facebook page. Passionate about modern infrastructure and microservices, I aim to help others understand and leverage cloud-native technologies for scalable, efficient solutions.

Welcome to Day 3! Now that you’ve created your first resource, let’s dive deeper into Providers - the plugins that allow Terraform to interact with cloud platforms, SaaS providers, and other APIs.

🎯 Today’s Goals

  • Understand what Terraform providers are

  • Learn provider configuration in detail

  • Explore provider versioning and locking

  • Master the AWS provider

  • Create a complete VPC network infrastructure

πŸ”Œ What Are Terraform Providers?

Providers are plugins that enable Terraform to interact with cloud platforms, SaaS services, and APIs.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Terraform  β”‚
β”‚     Core     β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ Uses plugins to communicate
       β”‚
   β”Œβ”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚                                    β”‚
β”Œβ”€β”€β–Όβ”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  AWS   β”‚  β”‚  Azure   β”‚  β”‚  Google   β”‚
β”‚Providerβ”‚  β”‚ Provider β”‚  β”‚ Provider  β”‚
β””β”€β”€β”€β”¬β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
    β”‚             β”‚              β”‚
    β–Ό             β–Ό              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  AWS   β”‚   β”‚ Azure  β”‚    β”‚   GCP    β”‚
β”‚  API   β”‚   β”‚  API   β”‚    β”‚   API    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Think of providers as translatorsβ€”they translate your HCL code into API calls for the target platform.

πŸ“¦ Provider Types

1. Official Providers (by HashiCorp)

  • AWS, Azure, Google Cloud

  • Maintained by HashiCorp

  • Highest quality and reliability

2. Partner Providers

  • Datadog, Kubernetes, Docker

  • Maintained by the company

  • Verified by HashiCorp

3. Community Providers

  • Built by community members

  • Various quality levels

  • Use with caution in production

4. Archived Providers

  • No longer maintained

  • Avoid using these

πŸ—οΈ Provider Configuration Structure

Basic Provider Configuration

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

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

Breaking It Down

1. Terraform Block:

terraform {
  required_providers {
    # Provider requirements
  }
}
  • Specifies Terraform settings

  • Defines which providers are needed

  • Sets version constraints

2. Provider Source:

source = "hashicorp/aws"
  • Format: namespace/provider-name

  • hashicorp = namespace (publisher)

  • aws = provider name

  • Terraform downloads from: registry.terraform.io

3. Version Constraint:

version = "~> 5.0"

Version operators:

  • = 5.0.0 - Exactly version 5.0.0

  • != 5.0.0 - Any version except 5.0.0

  • > 5.0.0 - Greater than 5.0.0

  • >= 5.0.0 - Greater than or equal to 5.0.0

  • < 5.0.0 - Less than 5.0.0

  • <= 5.0.0 - Less than or equal to 5.0.0

  • ~> 5.0 - Any 5.x version (pessimistic constraint)

Pessimistic Constraint Explained:

  • ~> 5.0 allows 5.1, 5.2, but NOT 6.0

  • ~> 5.0.0 allows 5.0.1, 5.0.2, but NOT 5.1.0

πŸ” AWS Provider Configuration Methods

export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_DEFAULT_REGION="us-east-1"
provider "aws" {
  # No explicit configuration needed
  # Uses environment variables
}
provider "aws" {
  region                   = "us-east-1"
  shared_credentials_files = ["~/.aws/credentials"]
  profile                  = "default"
}
provider "aws" {
  region     = "us-east-1"
  access_key = "your-access-key"      # ❌ Never do this!
  secret_key = "your-secret-access-key"  # ❌ Security risk!
}

⚠️ Never hardcode credentials in your code!

Method 4: IAM Role (Best for EC2/ECS)

When running Terraform on AWS resources:

provider "aws" {
  region = "us-east-1"
  # Automatically uses instance IAM role
}

🌍 Multiple Provider Configurations

You can configure the same provider multiple times for different regions or accounts:

# Default provider (us-east-1)
provider "aws" {
  region = "us-east-1"
}

# Additional provider for another region
provider "aws" {
  alias  = "west"
  region = "us-west-2"
}

# Use in resources
resource "aws_s3_bucket" "east_bucket" {
  bucket = "my-east-bucket"
  # Uses default provider (us-east-1)
}

resource "aws_s3_bucket" "west_bucket" {
  bucket   = "my-west-bucket"
  provider = aws.west  # Explicitly use west provider
}

πŸ”’ Provider Version Locking

After running terraform init, Terraform creates .terraform.lock.hcl:

# This file is maintained automatically by "terraform init".
provider "registry.terraform.io/hashicorp/aws" {
  version     = "5.31.0"
  constraints = "~> 5.0"
  hashes = [
    "h1:xxx...",
    "zh:xxx...",
  ]
}

Why this matters:

  • Ensures team uses same provider version

  • Prevents unexpected changes from updates

  • Should be committed to version control

To update providers:

terraform init -upgrade

πŸ§ͺ Hands-On Lab: Build a Complete VPC Network

Let’s build a real network infrastructure in AWS!

What We’ll Create

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚         VPC                 β”‚
                    β”‚    10.0.0.0/16              β”‚
                    β”‚                             β”‚
                    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
                    β”‚  β”‚   Public Subnet    β”‚     β”‚
                    β”‚  β”‚   10.0.1.0/24      β”‚     β”‚
                    β”‚  β”‚                    β”‚     β”‚
                    β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚     β”‚
                    β”‚  β”‚  β”‚  EC2 Instanceβ”‚  β”‚     β”‚
                    β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚     β”‚
                    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
                    β”‚            β”‚                β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                 β”‚
                         β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                         β”‚ Internet Gatewayβ”‚
                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                 β”‚
                                 β–Ό
                            Internet

Step 1: Create Project Directory

mkdir terraform-vpc-lab
cd terraform-vpc-lab

Step 2: Create main.tf

# Terraform configuration
terraform {
  required_version = ">= 1.0"

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

# AWS Provider configuration
provider "aws" {
  region = "us-east-1"

  default_tags {
    tags = {
      Project     = "TerraformLearning"
      ManagedBy   = "Terraform"
      Environment = "Development"
    }
  }
}

# Create a VPC
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "main-vpc"
  }
}

# Create an Internet Gateway
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "main-igw"
  }
}

# Create a Public Subnet
resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "us-east-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "public-subnet"
  }
}

# Create a Route Table
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }

  tags = {
    Name = "public-route-table"
  }
}

# Associate Route Table with Subnet
resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

# Create a Security Group
resource "aws_security_group" "web" {
  name        = "web-security-group"
  description = "Allow HTTP and SSH traffic"
  vpc_id      = aws_vpc.main.id

  # Allow SSH from anywhere (for learning - restrict in production!)
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # Allow HTTP from anywhere
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # Allow all outbound traffic
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "web-sg"
  }
}

Step 3: Initialize Terraform

terraform init

You’ll see Terraform download the AWS provider.

Step 4: Format and Validate

terraform fmt
terraform validate

Step 5: Plan the Deployment

terraform plan

Review the output carefully:

  • Count the resources to be created (should be 6)

  • Notice the dependencies (e.g., IGW depends on VPC)

  • See how resources reference each other

Step 6: Apply the Configuration

terraform apply

Type yes when prompted.

Expected output:

aws_vpc.main: Creating...
aws_vpc.main: Creation complete after 3s [id=vpc-xxx]
aws_internet_gateway.main: Creating...
aws_subnet.public: Creating...
...
Apply complete! Resources: 6 added, 0 changed, 0 destroyed.

Step 7: Verify in AWS Console

  1. Go to VPC Dashboard

  2. Check:

    • VPCs: See β€œmain-vpc”

    • Subnets: See β€œpublic-subnet”

    • Internet Gateways: See β€œmain-igw”

    • Route Tables: See β€œpublic-route-table”

    • Security Groups: See β€œweb-sg”

Step 8: Examine Resource Dependencies

terraform graph

This shows the dependency graph. To visualize it:

terraform graph | dot -Tpng > graph.png

(Requires Graphviz: brew install graphviz or apt install graphviz)

Step 9: Inspect Specific Resources

# Show all resources
terraform show
# Show specific resource
terraform state show aws_vpc.main

Step 10: Understanding Resource References

Notice in our code:

vpc_id = aws_vpc.main.id

This creates an implicit dependency:

  • Terraform knows the subnet depends on the VPC

  • It creates the VPC first, then the subnet

  • Format: resource_type.resource_name.attribute

Step 11: Clean Up

terraform destroy

Type yes to confirm.

Terraform will destroy resources in the correct order (reverse of creation).

πŸŽ“ Understanding Default Tags

Notice this in our provider block:

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

  default_tags {
    tags = {
      Project     = "TerraformLearning"
      ManagedBy   = "Terraform"
      Environment = "Development"
    }
  }
}

Default tags are automatically applied to ALL resources:

  • No need to repeat in each resource

  • Easy to update globally

  • Ensures consistent tagging

Individual resource tags merge with default tags.

πŸ“Š Provider Configuration Best Practices

βœ… DO:

  1. Always specify provider version constraints

  2. Use ~> for flexibility with safety

  3. Commit .terraform.lock.hcl to version control

  4. Use environment variables or shared credentials

  5. Set default tags for consistent resource tagging

  6. Use separate providers for different regions

❌ DON’T:

  1. Hardcode credentials in .tf files

  2. Use >= 0.0.0 (too permissive)

  3. Skip version constraints

  4. Ignore the lock file

  5. Use community providers without research

πŸ” Useful Provider Commands

# Show providers used in configuration
terraform providers
# Show dependency information
terraform providers schema
# Update providers to latest allowed version
terraform init -upgrade
# Download providers without other init steps
terraform providers mirror ./providers

πŸ“ Summary

Today you learned:

  • βœ… What Terraform providers are and how they work

  • βœ… How to configure the AWS provider

  • βœ… Provider versioning and version constraints

  • βœ… Provider version locking with .terraform.lock.hcl

  • βœ… Multiple provider configurations

  • βœ… Default tags for consistent resource tagging

  • βœ… How to reference resources (implicit dependencies)

  • βœ… Built a complete VPC network infrastructure

πŸš€ Tomorrow’s Preview

Day 4: Terraform Basics - Variables & Outputs

Tomorrow we’ll:

  • Learn about input variables

  • Create reusable configurations

  • Use output values to share data

  • Build a parameterized infrastructure

  • Make our code more flexible and DRY

πŸ’­ Challenge Exercise

Modify today’s VPC lab to:

  1. Add a second public subnet in us-east-1b

  2. Create a private subnet in 10.0.2.0/24

  3. Add a security group for databases (port 3306)

Hints:

  • Copy the subnet resource and change values

  • Private subnets don’t need map_public_ip_on_launch

  • Use the same VPC ID for all resources


Happy Learning! πŸŽ‰

Thanks For Reading, Follow Me For More

Subscribe youtube channel for the recap videos

Have a great day!..

← Day 2: Installing Terraform | Day 4: Variables & Outputs β†’


Remember: Understanding providers is crucialβ€”they’re the foundation of all Terraform configurations!

T

Thank you!

More from this blog

S

StackOps - Diary

33 posts

Welcome to the StackOps - Diary. We’re dedicated to empowering the tech community. We delve into cloud-native and microservices technologies, sharing knowledge to build modern, scalable solutions.