By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
For engineers who need to ship, not just study.
Outputs in Terraform are how you expose data from your infrastructure—like an EC2 instance’s public IP, an RDS endpoint, or a VPC ID—so other parts of your code (or other teams) can use it. Cross-module outputs let you pass data between Terraform modules, turning a monolithic script into a reusable, maintainable system.
terraform state
"vpc-123456"
db
app
output
sensitive = true
aws_instance.web.public_ip
description
"The public IP of the web server"
main.tf
outputs.tf
terraform output
terraform output -json
jq
depends_on
terraform_remote_state
sensitive
>= 1.0.0
aws configure
Deploy a simple web app with: 1. A VPC (defined in a network module).2. An EC2 instance (defined in a compute module) that uses the VPC’s subnet ID.3. Output the EC2 instance’s public IP to the CLI.
network
compute
web-app/ ├── main.tf # Root module ├── outputs.tf # Root outputs ├── modules/ │ ├── network/ # VPC module │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ └── compute/ # EC2 module │ ├── main.tf │ ├── outputs.tf │ └── variables.tf
modules/network/main.tf:
modules/network/main.tf
resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16" tags = { Name = "main-vpc" } } resource "aws_subnet" "public" { vpc_id = aws_vpc.main.id cidr_block = "10.0.1.0/24" tags = { Name = "public-subnet" } }
modules/network/outputs.tf:
modules/network/outputs.tf
output "vpc_id" { description = "The ID of the VPC" value = aws_vpc.main.id } output "subnet_id" { description = "The ID of the public subnet" value = aws_subnet.public.id }
modules/compute/main.tf:
modules/compute/main.tf
resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" # Amazon Linux 2 (us-east-1) instance_type = "t2.micro" subnet_id = var.subnet_id # Passed from the root module tags = { Name = "web-server" } }
modules/compute/variables.tf:
modules/compute/variables.tf
variable "subnet_id" { description = "The subnet ID where the EC2 instance will be launched" type = string }
modules/compute/outputs.tf:
modules/compute/outputs.tf
output "public_ip" { description = "The public IP of the EC2 instance" value = aws_instance.web.public_ip }
main.tf:
module "network" { source = "./modules/network" } module "compute" { source = "./modules/compute" subnet_id = module.network.subnet_id # Consume the output from the network module }
outputs.tf:
output "web_server_ip" { description = "The public IP of the web server" value = module.compute.public_ip # Consume the output from the compute module }
bash terraform init
bash terraform plan terraform apply -auto-approve
bash terraform output web_server_ip
"54.165.123.45"
bash aws ec2 describe-instances --instance-ids $(terraform output -raw web_server_ip | xargs -I {} aws ec2 describe-instances --filters "Name=ip-address,Values={}" --query "Reservations[0].Instances[0].InstanceId" --output text)
hcl output "db_password" { value = aws_db_instance.default.password sensitive = true }
count
for_each
hcl output "instance_ips" { value = { for k, v in aws_instance.web : k => v.public_ip } }
hcl output "vpc_id" { description = "The ID of the VPC (used by compute and database modules)" value = aws_vpc.main.id }
id
name
vpc_id
web_server_ip
Error: Cycle: module.network, module.compute
null
count = 0
try()
coalesce()
output "public_ip" { value = aws_instance.web }
✅ output "public_ip" { value = aws_instance.web.public_ip }
output "public_ip" { value = aws_instance.web.public_ip }
Cross-module outputs: "How do you reference an output from a module named network in another module?"
var.vpc_id
✅ module.network.vpc_id
module.network.vpc_id
Sensitive outputs: "How do you prevent a database password from appearing in Terraform logs?"
✅ output "db_password" { value = aws_db_instance.default.password; sensitive = true }
output "db_password" { value = aws_db_instance.default.password; sensitive = true }
Remote state outputs: "How do you fetch the VPC ID from a remote state file stored in S3?" hcl data "terraform_remote_state" "network" { backend = "s3" config = { bucket = "my-terraform-state" key = "network/terraform.tfstate" region = "us-east-1" } } output "vpc_id" { value = data.terraform_remote_state.network.outputs.vpc_id }
hcl data "terraform_remote_state" "network" { backend = "s3" config = { bucket = "my-terraform-state" key = "network/terraform.tfstate" region = "us-east-1" } } output "vpc_id" { value = data.terraform_remote_state.network.outputs.vpc_id }
instance_type = "t2.micro"
Challenge: Deploy a Lambda function that needs the ARN of an IAM role defined in a separate iam module. Use outputs to pass the ARN.
iam
Solution: 1. modules/iam/main.tf: hcl resource "aws_iam_role" "lambda" { name = "lambda-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "lambda.amazonaws.com" } }] }) } 2. modules/iam/outputs.tf: hcl output "lambda_role_arn" { value = aws_iam_role.lambda.arn } 3. modules/lambda/main.tf: hcl resource "aws_lambda_function" "example" { function_name = "example-lambda" role = var.lambda_role_arn handler = "index.handler" runtime = "nodejs14.x" filename = "lambda.zip" } 4. modules/lambda/variables.tf: hcl variable "lambda_role_arn" { type = string } 5. Root module: ```hcl module "iam" { source = "./modules/iam" }
modules/iam/main.tf
hcl resource "aws_iam_role" "lambda" { name = "lambda-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "lambda.amazonaws.com" } }] }) }
modules/iam/outputs.tf
hcl output "lambda_role_arn" { value = aws_iam_role.lambda.arn }
modules/lambda/main.tf
hcl resource "aws_lambda_function" "example" { function_name = "example-lambda" role = var.lambda_role_arn handler = "index.handler" runtime = "nodejs14.x" filename = "lambda.zip" }
modules/lambda/variables.tf
hcl variable "lambda_role_arn" { type = string }
module "lambda" { source = "./modules/lambda" lambda_role_arn = module.iam.lambda_role_arn } ```
Why it works: The iam module exposes the role ARN, and the lambda module consumes it via a variable.
lambda
output "vpc_id" { value = aws_vpc.main.id }
module.network.subnet_id
-json
terraform output web_server_ip
-raw
data.terraform_remote_state.network.outputs.vpc_id
for
output "instance_ips" { value = { for k, v in aws_instance.web : k => v.public_ip } }
terraform state show aws_instance.web
terraform output -raw web_server_ip
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.