Manage Terraform values including input variables, local values, and output values. Use when asked about "variables", "locals", "outputs", "input values", "how to pass values", "variable validation", "sensitive values", or when defining module interfaces, reusing expressions, or exposing data. Cover
Install
mkdir -p .claude/skills/terraform-values-luscii && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15331" && unzip -o skill.zip -d .claude/skills/terraform-values-luscii && rm skill.zipInstalls to .claude/skills/terraform-values-luscii
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Manage Terraform values including input variables, local values, and output values. Use when asked about "variables", "locals", "outputs", "input values", "how to pass values", "variable validation", "sensitive values", or when defining module interfaces, reusing expressions, or exposing data. Covers variable types, defaults, validation, precedence, locals usage patterns, and output configuration.About this skill
Terraform Values
Comprehensive guide to managing values in Terraform modules including input variables, local values, and output values. Learn how to create flexible, composable, and reusable modules.
When to Use This Skill
- User asks about "variables", "locals", "outputs", "input values"
- Questions about "how to pass values to modules"
- "Variable validation", "type constraints", "sensitive values"
- Defining module interfaces and boundaries
- Reusing expressions within modules
- Exposing module data to CLI, HCP Terraform, or other configurations
- Variable precedence and assignment methods
Value Types Overview
Object Syntax in Lists and Maps
HCL object syntax rules:
- Single-line object: Always use commas between key-value pairs.
Example:
log_sources = [ { name = "php", container = "app" }, { name = "nginx", container = "web" } ] - Multi-line object: Each key on a separate line, no commas needed.
Example:
log_sources = [ { name = "php" container = "app" }, { name = "nginx" container = "web" } ]
Maps and objects in variables, locals, and tests must follow these conventions.
Terraform uses three types of values to manage data flow:
| Type | Purpose | Scope | Reference |
|---|---|---|---|
| Variables | Module inputs | Module-specific | var.<NAME> |
| Locals | Reusable expressions | Module-scoped | local.<NAME> |
| Outputs | Module data export | Cross-module | output.<NAME> or module.<NAME>.<OUTPUT> |
Value Flow:
Variables (input) → Locals (processing) → Resources → Outputs (export)
Input Variables
Variables define the input interface of your module, letting consumers customize behavior without modifying source code.
Variable Definition
Basic Syntax:
variable "name" {
type = type_constraint
description = "Description of the variable"
default = default_value
sensitive = true/false
nullable = true/false
validation {
# Validation rules
}
}
Complete Example:
variable "instance_type" {
type = string
description = "EC2 instance type for the web server"
default = "t2.micro"
validation {
condition = can(regex("^t[23]\\.", var.instance_type))
error_message = "Instance type must be t2 or t3 family."
}
}
variable "subnet_id" {
type = string
description = "Subnet ID where the web server will be deployed"
# No default - required input
}
variable "environment" {
type = string
description = "Deployment environment name"
default = "dev"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
Variable Arguments
type
Specifies the value type constraint:
Simple Types:
variable "name" {
type = string
}
variable "count" {
type = number
}
variable "enabled" {
type = bool
}
Collection Types:
variable "tags" {
type = map(string)
}
variable "subnet_ids" {
type = list(string)
}
variable "ports" {
type = set(number)
}
Structural Types:
variable "config" {
type = object({
name = string
port = number
enabled = bool
})
}
variable "instances" {
type = list(object({
name = string
size = string
}))
}
variable "settings" {
type = map(object({
value = string
enabled = bool
}))
}
Optional Attributes:
variable "server" {
type = object({
name = string
port = optional(number, 80) # Default: 80
enabled = optional(bool, true) # Default: true
tags = optional(map(string), {}) # Default: {}
})
}
Any Type:
variable "custom_data" {
type = any
description = "Custom data of any type"
}
description
Always provide clear descriptions:
# ✅ Good - Specific and helpful
variable "subnet_id" {
type = string
description = "Subnet ID where the web server will be deployed"
}
# ❌ Bad - Vague
variable "subnet_id" {
type = string
description = "Subnet"
}
default
Makes variables optional:
# Required variable (no default)
variable "vpc_id" {
type = string
description = "VPC ID for resource deployment"
}
# Optional variable (has default)
variable "instance_type" {
type = string
description = "EC2 instance type"
default = "t2.micro"
}
# Complex default
variable "tags" {
type = map(string)
description = "Resource tags"
default = {
Terraform = "true"
ManagedBy = "terraform"
}
}
sensitive
Prevents values from appearing in CLI output:
variable "database_password" {
type = string
description = "Password for the RDS database instance"
sensitive = true
}
Behavior:
$ terraform plan
# Password value not shown in plan output
$ terraform output database_password
database_password = <sensitive>
Warning: Sensitive values are still stored in state. Use ephemeral (Terraform 1.10+) to omit from state entirely.
nullable
Controls whether null is accepted:
# Allows null (default behavior)
variable "optional_value" {
type = string
nullable = true
default = null
}
# Rejects null
variable "required_value" {
type = string
nullable = false
# If no value provided, Terraform errors
}
validation
Add custom validation rules:
Basic Validation:
variable "environment" {
type = string
description = "Deployment environment"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
Regex Validation:
variable "subnet_id" {
type = string
description = "AWS subnet ID"
validation {
condition = can(regex("^subnet-[a-f0-9]{8,17}$", var.subnet_id))
error_message = "Subnet ID must be a valid AWS subnet ID format."
}
}
Numeric Range Validation:
variable "max_size" {
type = number
description = "Maximum cluster size"
validation {
condition = var.max_size >= 1 && var.max_size <= 10
error_message = "Max size must be between 1 and 10."
}
}
Multiple Validations:
variable "instance_config" {
type = object({
type = string
size = number
})
validation {
condition = contains(["t2.micro", "t2.small", "t2.medium"], var.instance_config.type)
error_message = "Instance type must be t2.micro, t2.small, or t2.medium."
}
validation {
condition = var.instance_config.size >= 8 && var.instance_config.size <= 100
error_message = "Instance size must be between 8 and 100 GB."
}
}
Cross-Field Validation:
variable "min_size" {
type = number
}
variable "max_size" {
type = number
validation {
condition = var.max_size >= var.min_size
error_message = "Max size must be greater than or equal to min size."
}
}
Referencing Variables
Use var.<NAME> syntax:
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
subnet_id = var.subnet_id
tags = {
Environment = var.environment
Name = "${var.environment}-web-server"
}
}
Assigning Variable Values
Value Precedence
Terraform applies variable values in this order (highest to lowest):
- Command-line flags (
-var,-var-file) and HCP Terraform variables - Auto-loaded files (
*.auto.tfvars,*.auto.tfvars.json) in lexical order - terraform.tfvars.json
- terraform.tfvars
- Environment variables (
TF_VAR_*) - Variable default argument
Later sources override earlier ones.
Command-Line Variables
# Single variable
terraform apply -var="instance_type=t3.medium"
# Multiple variables
terraform apply \
-var="instance_type=t3.medium" \
-var="environment=prod"
# Complex types (use JSON)
terraform apply -var='subnet_ids=["subnet-12345","subnet-67890"]'
Variable Definition Files
Create .tfvars files:
# production.tfvars
instance_type = "t3.large"
environment = "prod"
subnet_ids = ["subnet-12345", "subnet-67890"]
enable_monitoring = true
Auto-loaded files:
*.auto.tfvars(loaded automatically)*.auto.tfvars.json(loaded automatically)terraform.tfvars(loaded automatically)terraform.tfvars.json(loaded automatically)
Manual loading:
terraform apply -var-file="production.tfvars"
JSON format:
{
"instance_type": "t3.large",
"environment": "prod",
"subnet_ids": ["subnet-12345", "subnet-67890"],
"enable_monitoring": true
}
Environment Variables
Use TF_VAR_ prefix:
# Simple values
export TF_VAR_instance_type=t3.medium
export TF_VAR_environment=staging
# Complex values (use JSON)
export TF_VAR_subnet_ids='["subnet-12345","subnet-67890"]'
export TF_VAR_config='{"key": "value", "enabled": true}'
terraform apply
HCP Terraform Variables
Set variables in workspace settings:
- Terraform Variables - Input to configuration
- Environment Variables - Shell environment (e.g.,
AWS_ACCESS_KEY_ID) - Variable Sets - Reusable groups applied to multiple workspaces
Variable Best Practices
Do's:
✅ Always add descriptions
variable "instance_type" {
type = string
description = "EC2 instance type for the web server"
default = "t2.micro"
}
✅ Use type constraints
variable "tags" {
type = map(string)
}
✅ Add validation for important values
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
✅
Content truncated.