variables.tf vs tfvards
difference between
root variables.tf
module variables.tf
environments/tfvars files
differece
Great 🎉 You’re on the right track. Let’s break it down piece by piece:
1. Your S3 Bucket Resource
resource "aws_s3_bucket" "this" {
bucket = var.bucket_name
tags = {
Environment = var.environment
ManagedBy = "Terraform"
}
}bucket = var.bucket_name→ the bucket name will come from a variable calledbucket_name.It’s not hardcoded here — you’ll define it in
variables.tfand pass it throughenvironments/dev.tfvars(orstage.tfvars,prod.tfvars).This makes it customizable per environment.
Example in environments/dev.tfvars:
bucket_name = "mycompany-dev-bucket-1234"
environment = "dev"In environments/prod.tfvars:
bucket_name = "mycompany-prod-bucket-1234"
environment = "prod"2. Lifecycle Rule (Compliance Example)
resource "aws_s3_bucket_lifecycle_configuration" "this" {
bucket = aws_s3_bucket.this.id
rule {
id = "expire_old_objects"
status = "Enabled"
expiration {
days = 365
}
}
}This adds a lifecycle rule → automatically deletes objects older than 365 days.
Enterprises use this for cost optimization and compliance.
You can add multiple rules (e.g., transition to Glacier after 90 days, delete after 1 year).
3. AWS Authentication
Since you already ran:
aws configureTerraform will automatically pick up credentials from your AWS CLI profile:
~/.aws/credentials(contains Access Key + Secret Key)~/.aws/config(contains region, output format)
✅ So you don’t need to hardcode credentials in Terraform. Terraform’s AWS provider automatically looks for them in this order:
Environment variables (
AWS_ACCESS_KEY_ID, etc.)Shared credentials file (
~/.aws/credentials)AWS CLI config (
~/.aws/config)EC2/ECS instance roles (if running inside AWS)
That means your setup is secure and enterprise-friendly. 🚀
4. Custom Variables
You can add any variable you want in variables.tf and override them in *.tfvars.
Example variables.tf:
variable "bucket_name" {
description = "The name of the S3 bucket"
type = string
}
variable "environment" {
description = "Environment name (dev/stage/prod)"
type = string
}Example dev.tfvars:
bucket_name = "mycompany-dev-bucket-1234"
environment = "dev"Then run:
terraform plan -var-file=environments/dev.tfvars
terraform apply -var-file=environments/dev.tfvars✅ So to answer your exact questions:
What is bucket name here? → It comes from
var.bucket_name, defined invariables.tfand set inenvironments/dev.tfvars(or stage/prod).Do I need to pass credentials? → No, Terraform will use the AWS CLI credentials you configured via
aws configure.What about custom variables? → You define them in
variables.tf, and override values per environment indev.tfvars,stage.tfvars,prod.tfvars.
👉 Do you want me to now show you the exact working code for each file in your structure (with variables.tf, dev.tfvars, main.tf calling the module, etc.) so you can just terraform init && terraform apply?
FLOW: dev.tfvars → root variables.tf → main.tf → module variables.tf → module main.tf → S3 bucket
why
Yes ✅ they can (and usually will) have the same variable names — but they live in different scopes:
🔹 Root variables.tf
variables.tfHere you declare what values the root module expects to receive (from tfvars or CLI).
# root/variables.tf
variable "bucket_name" {
description = "Name of the S3 bucket"
type = string
}This doesn’t create a bucket — it just tells Terraform “root module needs a variable called bucket_name”.
🔹 Module variables.tf
variables.tfHere you declare what the module expects from whoever calls it.
# modules/s3/variables.tf
variable "bucket_name" {
description = "Name of the S3 bucket"
type = string
}This doesn’t create a bucket either — it just says “this S3 module needs a variable bucket_name”.
🔹 Root main.tf
main.tfThis is where root passes its variable down to the module:
# root/main.tf
module "s3" {
source = "./modules/s3"
bucket_name = var.bucket_name # root variable passed into module
}🔹 Module main.tf
main.tfNow inside the module, the value is used to actually create the bucket:
# modules/s3/main.tf
resource "aws_s3_bucket" "this" {
bucket = var.bucket_name
}✅ Key Point
Yes, same name is fine (
bucket_namein root and in module).They are separate variables — root variable gets its value from
dev.tfvars, and then root forwards that value into the module.
It’s just like function arguments in Python/Java:
# Root
def root(bucket_name):
s3(bucket_name) # pass root variable to module
# Module
def s3(bucket_name):
print(bucket_name)Even though both are named bucket_name, they are in different scopes.
👉 Do you want me to draw a simple flow diagram showing how dev.tfvars → root variables.tf → module variables.tf → resource connects together? That usually clears it up instantly.
terraform apply -var-file=environments/dev.tfvars why?
Great question 👍 Let’s clear this up.
🔹 1. When you DON’T pass -var-file
-var-fileIf you just run:
terraform applyTerraform will look for:
Values in
terraform.tfvars(default filename it auto-loads).Any
*.auto.tfvarsfiles in the root folder (it auto-loads all of them).Environment variables (
TF_VAR_xxx).CLI flags (
-varor-var-file) if provided.
👉 So if you don’t pass -var-file, Terraform will only use variables it finds automatically (defaults, terraform.tfvars, *.auto.tfvars, or environment variables).
🔹 2. When you DO pass -var-file
-var-fileterraform apply -var-file=environments/dev.tfvarsHere you’re explicitly telling Terraform:
“Use values from dev.tfvars for this run.”
This is common in enterprise setups where you have:
environments/
dev.tfvars
stage.tfvars
prod.tfvarsThen you apply like:
terraform apply -var-file=environments/stage.tfvars
terraform apply -var-file=environments/prod.tfvars🔹 3. Enterprise Best Practice
Keep
dev.tfvars,stage.tfvars,prod.tfvarsseparate.Never hardcode prod values in
variables.tf.Pass the right file per environment.
In CI/CD pipelines (GitHub Actions, Jenkins, GitLab CI), the
-var-fileis usually set automatically based on branch or environment.
🔹 4. Shortcuts
If you want to avoid typing -var-file each time for dev:
Rename
environments/dev.tfvars→terraform.tfvars(Terraform auto-loads it).Or keep
dev.auto.tfvarsin root (Terraform auto-loads all*.auto.tfvars).
But in enterprise, we usually keep explicit -var-file so you don’t accidentally deploy to the wrong env.
✅ Answer:
Yes, you must pass
-var-file=environments/dev.tfvarsunless you rename it toterraform.tfvarsor*.auto.tfvars.In enterprise, passing
-var-fileis preferred because it’s safer and makes environments explicit.
👉 Do you want me to show you a real example of running terraform plan and terraform apply for dev, stage, and prod so you can see the workflow end-to-end?
Last updated