linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Knowledge base
  • Cheat sheet
  • Capstone
  • Interview prep
home/terraform/kb/Providers/aws-provider

kb/providers ── Providers ── beginner

AWS provider: configuration and where Terraform finds your keys

The AWS provider looks for credentials in several places in order: env variables, ~/.aws/credentials, the instance IAM role. Usually `aws configure` locally or a role on EC2 is enough, and you configure nothing else.

view as markdown

What the AWS provider does

The AWS provider is a translator plugin. You write resource "aws_s3_bucket" ... in HCL, and the provider turns that into an HTTP request to the AWS API, PUT /buckets/.... The plugin knows all 300+ AWS resource types: S3, EC2, IAM, Lambda, RDS, and so on.

The plugin is downloaded by terraform init (see tf-init) from the Terraform Registry.

Minimal configuration

hcl
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.60"
    }
  }
}
provider "aws" {
  region = "us-east-1"
}

No credentials are listed here. The provider finds them itself through the chain (see below).

Credentials chain: where the provider looks for keys

The AWS provider tries these places in order. The first one that works wins:

  1. Parameters in the provider block (access_key, secret_key). Do not do this in production: the credentials end up in your code.
  2. Environment variables:
    • AWS_ACCESS_KEY_ID
    • AWS_SECRET_ACCESS_KEY
    • AWS_SESSION_TOKEN (for temporary credentials)
    • AWS_DEFAULT_REGION or AWS_REGION
  3. Shared credentials file ~/.aws/credentials (created by aws configure).
  4. EC2 Instance Metadata Service (IMDS), when Terraform runs on an EC2 instance with an IAM role.
  5. ECS / EKS task role, for containerized environments.

The right approach for a developer:

bash
aws configure   # once: you enter the keys, and the provider finds them itself

The right approach for a production server: an IAM role on EC2, an ECS task role, or IRSA in EKS. The keys live nowhere; they are issued as short-lived credentials through IMDS.

Region: a required parameter

AWS services are regional: an S3 bucket in us-east-1 is not visible from eu-central-1. You can set the region three ways:

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

or with an env var:

bash
export AWS_DEFAULT_REGION=us-east-1
terraform apply

or in ~/.aws/config:

ini
[default]
region = us-east-1

If the region is set nowhere, terraform plan fails with the error "no valid credential sources found". The wording is confusing, but the real cause is the region or the keys.

default_tags: tags on everything

This is one of the most useful provider parameters:

hcl
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      Project     = "linuxlab-courses"
      Environment = "dev"
      ManagedBy   = "terraform"
      Owner       = "platform-team"
    }
  }
}

Now every resource gets these tags automatically. This:

  • Solves the "who created this?" problem in your cloud bills.
  • Makes resources easier to find and delete: aws ec2 describe-instances --filters Name=tag:Project,Values=linuxlab-courses.
  • Gives you a basis for FinOps reports.

If a resource has its own tags, they merge with default_tags. On a collision, the specific tags override the global ones.

assume_role: working with other accounts

Large companies often give each team its own AWS account, and cross-account access goes through an IAM role:

hcl
provider "aws" {
  region = "us-east-1"
  assume_role {
    role_arn     = "arn:aws:iam::123456789012:role/TerraformDeployerRole"
    session_name = "terraform-from-local"
    external_id  = "secret-shared-with-the-target-account"
  }
}

Here is what happens:

  1. The provider first walks the credentials chain and finds keys in an env variable or a file.
  2. With those keys it calls AWS STS AssumeRole and gets temporary credentials, valid for 1 hour.
  3. Every later call to the AWS API goes out with the temporary credentials.

This is much safer than storing the target account's keys.

Several regions at once

Use alias (see tf-provider-block):

hcl
provider "aws" {
  region = "us-east-1"   # default
}
provider "aws" {
  alias  = "europe"
  region = "eu-central-1"
}
resource "aws_s3_bucket" "us" {
  bucket = "my-us-bucket"
}
resource "aws_s3_bucket" "eu" {
  provider = aws.europe
  bucket   = "my-eu-bucket"
}

Pitfalls

  • Do not write access_key and secret_key in HCL. It goes into git, then into a public repository, then into a GitGuardian scan, and then the whole world sees your keys. Use env vars or aws configure.

  • region is not the same thing as an Availability Zone. A region is us-east-1, an AZ is us-east-1a. The AZ is usually set at the level of a specific resource.

  • It is easy to get lost between AWS profiles. If you have several profiles in ~/.aws/credentials, and AWS_PROFILE points to one while the env variable AWS_ACCESS_KEY_ID points to another, the env variable wins (per the credentials chain). Always check aws sts get-caller-identity before dangerous operations.

  • default_tags can conflict with provider-level limits. For example, an EBS volume does not support every tag type, and tags like aws:created-by are reserved by AWS.

  • assume_role costs time. Each STS call is one more HTTP request. It should not hurt, but on large applies it is noticeable.

§ команды

bash
aws sts get-caller-identity

Check which credentials the AWS CLI or Terraform is using right now. The first thing to run when you think 'why am I seeing the wrong infrastructure?'.

bash
aws configure

Interactive credentials setup. Creates `~/.aws/credentials` and `~/.aws/config`.

bash
aws configure list

Shows which credentials and region are active now, and where they came from (env vs file vs IAM).

bash
AWS_PROFILE=staging terraform plan

Run plan under a specific profile without switching the default one.

§ см. также

  • tf-provider-blockThe provider block: who Terraform will callThe provider block configures the plugin: which AWS region to talk to, which endpoints to use, which credentials to take. One block per provider is usually enough.
  • localstack-providerLocalStack: a learning AWS that lives in DockerLocalStack emulates the AWS API locally, inside a Docker container. Terraform thinks it is talking to real AWS, but no real resources are created and no money is spent. Ideal for learning and tests.
  • tf-initterraform init: the first command in any projectterraform init downloads the provider plugins (AWS, GCP, and so on), creates a lockfile that pins their versions, and prepares the working directory. Without it, neither plan nor apply will run.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies