Output Values
Output values are like return values for Terraform modules. They expose information about your infrastructure for use by other configurations, display to users, or integration with external tools.
Declaring Outputs
Declare output values using output blocks:
output "<NAME>" {
value = < EXPRESSION >
}
Basic Example
output "instance_ip" {
value = aws_instance . web . public_ip
description = "Public IP address of the web server"
}
Output Arguments
The value to export. Can be any Terraform expression. value = aws_instance . web . id
value = [ for i in aws_instance . web : i . private_ip ]
value = {
id = aws_instance.web.id
ip = aws_instance.web.public_ip
}
Human-readable description of the output’s purpose. description = "The public IP address of the web server"
Hide the value in Terraform output. Default is false.
Explicit dependencies for the output. depends_on = [
aws_instance . web ,
aws_security_group . web ,
]
Marks the output as ephemeral (not persisted in state).
Output Examples
Simple Values
output "instance_id" {
value = aws_instance . web . id
description = "ID of the EC2 instance"
}
output "public_ip" {
value = aws_instance . web . public_ip
}
Complex Values
output "instance_details" {
value = {
id = aws_instance.web.id
public_ip = aws_instance.web.public_ip
private_ip = aws_instance.web.private_ip
az = aws_instance.web.availability_zone
}
description = "Complete details of the instance"
}
Collection Outputs
output "all_instance_ips" {
value = aws_instance . web [ * ] . private_ip
description = "Private IP addresses of all instances"
}
output "instance_map" {
value = {
for instance in aws_instance . web :
instance. id => instance.private_ip
}
}
Computed Outputs
output "connection_string" {
value = "https:// ${ aws_instance . web . public_ip } :8080"
description = "Complete connection string"
}
output "uppercase_name" {
value = upper (var . instance_name )
}
Viewing Outputs
During Apply
Outputs are shown after terraform apply:
terraform apply
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
instance_id = "i-1234567890abcdef0"
public_ip = "54.123.45.67"
Query Outputs
View outputs without applying changes:
# All outputs
terraform output
# Specific output
terraform output instance_ip
# JSON format
terraform output -json
# Raw value (useful for scripts)
terraform output -raw instance_ip
Sensitive Outputs
Mark outputs containing secrets:
output "database_password" {
value = aws_db_instance . database . password
sensitive = true
}
Sensitive outputs:
Are hidden in terraform apply output
Show <sensitive> instead of the value
Can be viewed with terraform output
terraform output database_password
Sensitive outputs are still stored in plain text in the state file. Always encrypt your state file.
Module Outputs
Outputs are essential for module composition:
Child Module
# modules/web-app/outputs.tf
output "instance_id" {
value = aws_instance . app . id
description = "ID of the application instance"
}
output "endpoint" {
value = "https:// ${ aws_instance . app . public_ip } "
}
Root Module
# main.tf
module "web_app" {
source = "./modules/web-app"
instance_type = var . instance_type
}
output "web_app_id" {
value = module . web_app . instance_id
}
output "web_app_url" {
value = module . web_app . endpoint
}
Preconditions
Validate output values:
output "api_endpoint" {
value = aws_instance . api . public_ip
precondition {
condition = aws_instance . api . public_ip != ""
error_message = "API instance must have a public IP address."
}
}
From internal/configs/named_values.go:443-461, outputs support preconditions but not postconditions.
Deprecated Outputs
Mark outputs as deprecated:
output "old_endpoint" {
value = aws_instance . web . public_dns
deprecated = "Use 'endpoint' output instead"
}
Output Use Cases
Show important information to users:
output "next_steps" {
value = <<- EOT
Your infrastructure is ready!
SSH Command: ssh ubuntu@ ${ aws_instance . web . public_ip }
Web URL: http:// ${ aws_instance . web . public_ip }
EOT
}
Chaining Modules
Pass data between modules:
module "network" {
source = "./modules/network"
}
module "compute" {
source = "./modules/compute"
vpc_id = module . network . vpc_id
subnet_id = module . network . subnet_id
}
Export data for external tools:
# Use in scripts
INSTANCE_IP = $( terraform output -raw instance_ip )
ssh ubuntu@ $INSTANCE_IP
# Export to environment
export DB_HOST = $( terraform output -raw database_endpoint )
Remote State Data Source
Share outputs across configurations:
# Configuration A outputs
output "vpc_id" {
value = aws_vpc . main . id
}
# Configuration B reads outputs
data "terraform_remote_state" "network" {
backend = "s3"
config = {
bucket = "terraform-state"
key = "network/terraform.tfstate"
region = "us-west-2"
}
}
resource "aws_instance" "web" {
vpc_id = data . terraform_remote_state . network . outputs . vpc_id
}
Output Examples from Source
From internal/configs/testdata/valid-files/outputs.tf:
output "foo" {
value = "hello"
}
output "bar" {
value = local . bar
}
output "baz" {
value = "ssshhhhhhh"
sensitive = true
}
output "cheeze_pizza" {
description = "Nothing special"
value = "🍕"
}
output "π" {
value = 3.14159265359
depends_on = [
pizza . cheese ,
]
}
Output Naming
Output names must:
Start with a letter or underscore
Contain only letters, digits, underscores, and hyphens
Be unique within the configuration
output "instance_id" { } # Valid
output "instance-id" { } # Valid
output "_private_data" { } # Valid
output "2nd_instance" { } # Invalid
Implementation Details
From internal/configs/named_values.go:362-381:
type Output struct {
Name string
Description string
Expr hcl . Expression
DependsOn [] hcl . Traversal
Sensitive bool
Ephemeral bool
Deprecated string
Preconditions [] * CheckRule
DescriptionSet bool
SensitiveSet bool
EphemeralSet bool
DeprecatedSet bool
DeclRange hcl . Range
DeprecatedRange hcl . Range
}
Best Practices
Add Descriptions Always include descriptions to help users understand output purpose and usage.
Use Sensitive Flag Mark outputs containing credentials or secrets as sensitive.
Structured Data Group related values into objects for better organization.
Meaningful Names Use clear, descriptive names that indicate the output’s content.
Common Patterns
output "connection_info" {
value = {
host = aws_instance.web.public_ip
port = 22
username = "ubuntu"
}
description = "SSH connection information"
}
Resource IDs
output "resource_ids" {
value = {
vpc = aws_vpc.main.id
subnet = aws_subnet.public.id
instance = aws_instance.web.id
security_group = aws_security_group.web.id
}
}
Conditional Outputs
output "public_endpoint" {
value = var . create_public_ip ? aws_instance . web . public_ip : null
}
Filtered Lists
output "production_instances" {
value = [
for instance in aws_instance . web :
instance . id if instance . tags [ "Environment" ] == "production"
]
}
Troubleshooting
Output Not Shown
If outputs don’t appear:
Ensure the output block is valid
Check that resources exist in state
Verify expressions are correct
Sensitive Output Warning
Warning: Output "password" contains sensitive data
This is expected for sensitive outputs. Use -raw to view:
terraform output -raw password
Next Steps
Variables Learn about input variables
Modules Use outputs for module composition