D4 · Terraform Configuration

Variables, locals and outputs

make parameterizable and reusable. expose values to the outside. Locals are intermediate computed values. Mastering their precedence and behavior is key for the exam.

variable block: types and validation

# Full declaration of a variable
variable "instance_type" {
  type        = string              # data type
  default     = "t3.micro"          # default value (makes the variable optional)
  description = "EC2 instance type"      # documentation
  sensitive   = false               # if true, hides the value in logs

  validation {
    condition     = contains(["t3.micro", "t3.small", "t3.medium"], var.instance_type)
    error_message = "instance_type must be t3.micro, t3.small or t3.medium."
  }
}

# Variable with no default (REQUIRED — Terraform will prompt for the value)
variable "db_password" {
  type      = string
  sensitive = true
  description = "Database password"
}

# Variable with a complex type
variable "allowed_cidrs" {
  type    = list(string)
  default = ["10.0.0.0/8", "172.16.0.0/12"]
}

variable "tags" {
  type = map(string)
  default = {
    Environment = "dev"
    Team        = "platform"
  }
}

💡 Validation with condition

The validation block inside a variable lets you validate the value before Terraform runs the plan. The condition must be a boolean expression that uses var.name. If it evaluates to false, Terraform shows the error_message.

Assignment methods and precedence

Terraform evaluates variables in order of precedence. Methods with a higher number in the list override the earlier ones.

1 (lowest)

Default value in the variable {} block

default = "us-east-1"

2

terraform.tfvars file

aws_region = "us-west-2"

3

*.auto.tfvars files (alphabetical order)

prod.auto.tfvars — loaded automatically

4

TF_VAR_name environment variables

export TF_VAR_aws_region="eu-west-1"

5

-var-file=file.tfvars flag

terraform plan -var-file=prod.tfvars

6 (highest)

-var="key=value" flag

terraform plan -var="aws_region=ap-southeast-1"

# terraform.tfvars — loaded automatically if it exists in the directory
aws_region    = "us-east-1"
instance_type = "t3.small"
db_password   = "super-secret"    # ⚠️ do not commit if it contains secrets

# prod.auto.tfvars — loaded automatically (thanks to the .auto.)
environment = "prod"
instance_type = "t3.large"       # overrides terraform.tfvars

# Reference in code: var.variable_name
resource "aws_instance" "web" {
  instance_type = var.instance_type
  ami           = var.ami_id
}

🎯 For the exam: the precedence question

The exam often asks: "If variable X is defined as a default, in terraform.tfvars and with -var, which value is used?". The answer is -var (the highest precedence). Memorize the order: default → tfvars → auto.tfvars → TF_VAR → -var-file → -var.

sensitive variables and

The sensitive = true attribute on a variable tells Terraform to hide its value in the CLI output (plan, apply). However, it has important limitations.

✅ What sensitive = true DOES do

  • • Hides the value in plan output: shows (sensitive value)
  • • Hides the value in apply output
  • • If used in an output, the output automatically inherits sensitive
  • • Prevents accidental exposure in CI/CD logs

⚠️ What sensitive = true does NOT do

  • • Does NOT encrypt the value in terraform.tfstate — it appears in plain text
  • • Does not encrypt the value in the backend
  • • Does not prevent Terraform from using the value
  • • For real secrets, use a remote backend with encryption (S3+KMS, HCP Terraform)
variable "db_password" {
  type      = string
  sensitive = true
}

# In the plan you will see:
# + db_password = (sensitive value)  ← value hidden in the CLI

# BUT in terraform.tfstate you will see:
# "db_password": "my-secret-password"  ← in plain text ⚠️

# That's why it's recommended to:
# 1. Use a remote backend with encryption (S3 + KMS or HCP Terraform)
# 2. Retrieve secrets from Vault/Secrets Manager at runtime

Ephemeral values (ephemeral) — Terraform 1.10+

are values that Terraform uses in memory during plan/apply but does not persist in the state or in logs. Designed to handle real secrets (passwords, tokens) securely.

# Ephemeral variable — not written to state
variable "db_password" {
  type      = string
  ephemeral = true    # new in Terraform 1.10+
}

# Ephemeral resource — data that does not persist in state
ephemeral "aws_secretsmanager_secret_version" "db_creds" {
  secret_id = "prod/db/password"
}

# Write-only argument — accepts an ephemeral value on a resource
resource "aws_db_instance" "main" {
  identifier = "prod-db"
  engine     = "postgres"
  password   = ephemeral.aws_secretsmanager_secret_version.db_creds.secret_string
  # password has write_only = true: sent to the API but not saved in state
}

variable ephemeral

An input value that is not saved in state. Ideal for passwords and tokens only needed during the apply.

ephemeral resource

An ephemeral {} block for external data (Vault, Secrets Manager) whose value must not persist in state.

write-only argument

A resource attribute that Terraform sends to the provider API but does not store in state or show in the plan.

🎯 For the exam (004)

  • • sensitive = true hides the value in CLI output but it is still saved in the state
  • • ephemeral = true (Terraform 1.10+) makes the value not persist in the state at all — real security for secrets
  • • ephemeral resources can be used with secret providers (Vault, AWS Secrets Manager)

output block

Outputs expose module values to the outside world: to the user (shown in the apply), to the parent module (accessible as module.name.output), and as state data (accessible via terraform output).

# Declaring outputs
output "vpc_id" {
  value       = aws_vpc.main.id
  description = "ID of the main VPC"
}

output "db_endpoint" {
  value       = aws_db_instance.main.endpoint
  description = "Database connection endpoint"
  sensitive   = true           # hidden in CLI, but available to parent modules
}

output "subnet_ids" {
  value       = aws_subnet.public[*].id   # list of IDs with a splat expression
  description = "IDs of the public subnets"
}

# Access from a parent module:
# module.networking.vpc_id
# module.networking.subnet_ids

# Access from the CLI:
# terraform output vpc_id
# terraform output -json
ArgumentRequiredDescription
value✅ YesThe expression whose result is exposed as the output
description❌ NoDocumentation for the output (a good practice, always recommended)
sensitive❌ NoIf true, hides the value in the CLI. Inherited if value references a sensitive variable.
depends_on❌ NoDeclares explicit dependencies when the value does not have implicit ones

locals block

Locals are values computed inside the module that you can reuse in multiple places. Unlike variables, they cannot be overridden from outside the module.

# locals block (plural: the block is called "locals")
locals {
  # Combine variables to build a standard name
  name_prefix = "${var.project}-${var.environment}"

  # Common tags applied to all resources
  common_tags = {
    Project     = var.project
    Environment = var.environment
    ManagedBy   = "terraform"
    Owner       = var.team
  }

  # Complex calculation
  is_production = var.environment == "prod"
  instance_type = local.is_production ? "t3.large" : "t3.micro"
}

# Access: local.name (singular: "local")
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags = merge(local.common_tags, {
    Name = "${local.name_prefix}-vpc"
  })
}
Featurevariable {}locals {}
Configurable from outside?✅ Yes — that is its purpose❌ No — internal to the module
Can it contain expressions?Only in default and validation✅ Yes — any HCL expression
Access prefixvar.namelocal.name (singular)
Declaration blockvariable "name" {}locals {} (a single block with several keys)
When to use itA parameter the user definesA derived/computed value internal to the module

Did you get this topic?

Test what you just learned

An engineer defines a db_password variable with sensitive = true and uses it as an argument on an aws_db_instance resource. They then run terraform apply successfully. Where will the password appear in plain text?

Ready to test "Variables, Locals and Outputs"?

Put what you learned to the test with original Terraform Associate exam questions.

Start Terraform Associate mock exam

Unlimited mock exams with the Pro plan

Log in to track your progress.