DevOpsLesson
DevOpsLesson

Free, comprehensive DevOps tutorials and learning roadmaps. Master Docker, Kubernetes, CI/CD, and more.

Stay Updated

Get notified about new tutorials and features.

Tutorials

  • What is DevOps?
  • Docker Tutorial
  • Terraform Tutorial
  • CI/CD Pipeline
  • All Tutorials

Roadmaps

  • DevOps Engineer
  • Cloud Engineer
  • SRE Path
  • All Roadmaps

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 DevOpsLesson. All rights reserved.

DOCKERKUBERNETESTERRAFORMAWSCI/CDLINUXGITDEVOPS ROADMAPCLOUD ROADMAPSRE ROADMAPGIT CHEATSHEETDOCKER CHEATSHEETK8S CHEATSHEETTF CHEATSHEETLINUX CHEATSHEETDOCKERFILE LINTERYAML VALIDATORCRON PARSERREGEX TESTER

Terraform Tutorial

Introduction to Terraform
Installing Terraform
The Terraform Core Workflow
Terraform Variables and Outputs
Terraform State and Backends
Terraform Modules
Terraform Data Sources
Terraform Count and for_each
Terraform Expressions and Functions
Terraform Dynamic Blocks
Terraform Workspaces
Terraform with AWS
Terraform Provisioners
Terraform CI/CD Pipeline
Terraform Security

Terraform Output Values

PreviousPrev
Next

Learn Terraform output values in depth, including output blocks, sensitive outputs, terraform output commands, module outputs, and CI/CD automation patterns.

What Are Output Values in Terraform?

Terraform output values are named results that Terraform prints after it creates or updates infrastructure. They answer a simple but important question: after Terraform finishes, how do you get back the values you care about?

For example, after creating infrastructure you often want to know:

  • the public IP of a server
  • the DNS name of a load balancer
  • the ARN of an IAM role
  • the URL of an application
  • the ID of a VPC or subnet

Those values usually come from resources created during terraform apply. Output values make them easy to expose in a clean, reusable way.

A basic example looks like this:

output "instance_public_ip" {
  description = "Public IP address of the web server"
  value       = aws_instance.web.public_ip
}

After terraform apply, Terraform can display the result:

instance_public_ip = "54.12.34.56"

Output values are useful for both humans and automation. A person can quickly see important infrastructure details, while a CI/CD script can read outputs and pass them to later steps.

Why Output Values Matter

It is possible to inspect Terraform state manually, but that is not a good workflow. State is verbose, internal, and often sensitive. Output values give you a small curated interface to the most important results.

They help in several ways:

1. Better usability

Instead of searching through a long plan or cloud console, you can expose exactly what matters.

2. Module communication

Outputs are how child modules publish values back to the root module or to other modules.

3. Automation

Deployment scripts, Ansible playbooks, Kubernetes bootstrap steps, and CI/CD jobs often depend on values generated by Terraform.

4. Documentation through code

A good output block explains which values a module intentionally exposes.

Declaring Output Values with output Blocks

An output is declared with an output block:

output "alb_dns_name" {
  description = "DNS name of the application load balancer"
  value       = aws_lb.app.dns_name
}

Common arguments in an output block

ArgumentPurpose
valueThe expression Terraform should expose
descriptionHuman-readable explanation of the output
sensitiveHides the value from normal terminal output

value is required. description is strongly recommended. sensitive is optional and useful for secrets.

Simple Output Examples

Resource attribute output

output "bucket_name" {
  description = "Name of the S3 bucket used for application logs"
  value       = aws_s3_bucket.logs.id
}

URL output

output "application_url" {
  description = "Base URL for the deployed application"
  value       = "https://${aws_lb.app.dns_name}"
}

List output

output "public_subnet_ids" {
  description = "IDs of public subnets"
  value       = aws_subnet.public[*].id
}

Map output

output "instance_private_ips" {
  description = "Private IPs of application instances keyed by name"
  value = {
    for instance in aws_instance.app :
    instance.tags.Name => instance.private_ip
  }
}

Outputs can contain simple values or richer data structures, as long as the expression is valid Terraform.

A Realistic Example

Imagine a small AWS deployment that creates a VPC, subnets, and an application load balancer.

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

output "public_subnet_ids" {
  description = "Public subnet IDs"
  value       = aws_subnet.public[*].id
}

output "alb_dns_name" {
  description = "Public DNS name of the load balancer"
  value       = aws_lb.app.dns_name
}

output "application_url" {
  description = "URL users should open in a browser"
  value       = "https://${aws_lb.app.dns_name}"
}

This is much more user-friendly than telling people to inspect state or hunt for resource attributes.

Sensitive Outputs

Some outputs should not be displayed openly in the terminal, especially if they contain secrets.

output "db_password" {
  description = "Database password"
  value       = var.db_password
  sensitive   = true
}

When Terraform prints outputs after apply, a sensitive output is hidden:

db_password = <sensitive>

Very important warning

Sensitive outputs are hidden in terminal output, but they are not removed from Terraform state. If the value is stored in state by Terraform or by the provider, anyone with state access may still be able to retrieve it.

So sensitive = true improves safety in logs and command output, but it is not a substitute for:

  • securing remote state
  • restricting access to backend storage
  • using secret managers where appropriate

Using the terraform output Command

After you apply a configuration, you can retrieve outputs at any time with the terraform output command.

Show all outputs

terraform output

Example:

alb_dns_name = "app-alb-123456.us-east-1.elb.amazonaws.com"
application_url = "https://app-alb-123456.us-east-1.elb.amazonaws.com"
vpc_id = "vpc-0abc123def456"

This is useful when you want a quick summary of the deployment.

Show a specific output

terraform output alb_dns_name

Result:

app-alb-123456.us-east-1.elb.amazonaws.com

This is convenient in scripts or when you only care about one value.

Use -json for machine-readable output

terraform output -json

Example shape:

{
  "alb_dns_name": {
    "sensitive": false,
    "type": "string",
    "value": "app-alb-123456.us-east-1.elb.amazonaws.com"
  },
  "vpc_id": {
    "sensitive": false,
    "type": "string",
    "value": "vpc-0abc123def456"
  }
}

JSON output is the preferred format for automation because scripts can parse it reliably.

Output command examples in practice

Fetch a load balancer URL for testing

terraform output application_url

Save all outputs for another tool

terraform output -json

A script could then parse the JSON and export variables for later pipeline stages.

Read a single output cleanly in shell automation

Many teams use:

terraform output -json application_url

or parse the full JSON with tools available in their environment. The key lesson is that Terraform can provide machine-readable output, which is much better than scraping human-oriented terminal text.

Passing Outputs Between Modules

Outputs are essential in Terraform module design.

A child module exposes values using output blocks, and the parent module reads them with:

module.<module_name>.<output_name>

Child module example

Imagine a module that creates a VPC.

# modules/vpc/outputs.tf
output "vpc_id" {
  description = "ID of the created VPC"
  value       = aws_vpc.main.id
}

output "public_subnet_ids" {
  description = "IDs of the public subnets"
  value       = aws_subnet.public[*].id
}

Root module using those outputs

module "network" {
  source = "./modules/vpc"

  project_name = var.project_name
  environment  = var.environment
  vpc_cidr     = var.vpc_cidr
}

module "app" {
  source = "./modules/app"

  vpc_id     = module.network.vpc_id
  subnet_ids = module.network.public_subnet_ids
}

This is how Terraform modules communicate safely and intentionally.

Why outputs matter in module design

A good module does not expose every possible internal detail. It exposes the values that callers actually need.

For a VPC module, useful outputs might include:

  • VPC ID
  • public subnet IDs
  • private subnet IDs
  • route table IDs

For an EC2 module, useful outputs might include:

  • instance ID
  • private IP
  • public IP
  • security group ID

Outputs define the public contract of the module.

Using Outputs in CI/CD Scripts

Terraform outputs are frequently used in deployment pipelines.

Imagine a pipeline that:

  1. runs terraform apply
  2. reads the application URL
  3. runs smoke tests against the deployed service

Example workflow:

terraform apply -auto-approve
terraform output application_url

A CI/CD job could use the output value to:

  • run a health check
  • create a deployment annotation
  • pass the URL to integration tests
  • store the endpoint as a pipeline variable

Example scenario: DNS or app endpoint

Suppose Terraform creates an Application Load Balancer and your test step needs its hostname.

output "application_url" {
  description = "Public endpoint for smoke tests"
  value       = "https://${aws_lb.app.dns_name}"
}

Now your pipeline can read this output and test the environment automatically.

Example scenario: Kubernetes bootstrap

If Terraform provisions an EKS cluster, outputs might provide:

  • cluster name
  • cluster endpoint
  • node security group ID
  • OIDC provider ARN

Downstream automation can then configure kubectl, install Helm charts, or update DNS.

Best Practices for Output Values

1. Output what is useful, not everything

Too many outputs make a module noisy. Expose the values callers or operators truly need.

2. Always add descriptions

Descriptions make outputs self-documenting and much easier to understand in code reviews.

3. Mark secrets as sensitive

If an output includes confidential data, set sensitive = true to reduce accidental exposure in logs.

4. Prefer stable, meaningful outputs

Useful outputs are usually IDs, ARNs, names, URLs, or lists of created resources—not every internal attribute.

5. Think of outputs as a module API

Once other code depends on your outputs, changing or removing them can break consumers. Design them intentionally.

Common Beginner Mistakes

Outputting values that should stay internal

Not every resource attribute deserves to be an output. If no one needs it outside the module, leave it internal.

Forgetting to mark secrets as sensitive

If an output contains credentials or secret tokens, always mark it sensitive.

Assuming sensitive outputs are fully secure

Remember: hidden in terminal output does not mean removed from state.

Creating outputs but never using them

Outputs should serve a clear purpose for operators, parent modules, or automation.

A Full Example: Outputs for a Web Stack

output "vpc_id" {
  description = "ID of the VPC used by the application"
  value       = aws_vpc.main.id
}

output "alb_dns_name" {
  description = "DNS name of the application load balancer"
  value       = aws_lb.app.dns_name
}

output "application_url" {
  description = "Public HTTPS URL for the application"
  value       = "https://${aws_lb.app.dns_name}"
}

output "app_security_group_id" {
  description = "Security group ID attached to application instances"
  value       = aws_security_group.app.id
}

output "private_instance_ips" {
  description = "Private IP addresses of app servers"
  value       = aws_instance.app[*].private_ip
}

This gives both humans and automation a concise summary of the deployment.

Final Thoughts

Output values are one of Terraform's simplest features, but they are incredibly useful. They turn raw infrastructure details into an intentional interface. For beginners, they are the easiest way to answer questions like, "What did Terraform just create for me?" For teams, they are the glue that connects modules and automation.

A practical summary is:

  • Resources create infrastructure
  • Outputs expose important results
  • Modules publish outputs to parents
  • CI/CD pipelines consume outputs for automation
  • Sensitive outputs hide terminal display but not state contents

If you treat outputs like a clean API for your Terraform code, your configurations will be easier to reuse and easier to automate.


Knowledge Check

Exercise

Question 1: Output Purpose

What is the main purpose of a Terraform output value?

Exercise

Question 2: Sensitive Outputs

What does sensitive = true do in a Terraform output block?

Exercise

Question 3: Module Outputs

How does a root module usually reference an output named vpc_id from a child module called network?

PreviousPrev
Next

Continue Learning

Terraform Variables and Outputs

Learn how Terraform input variables, local values, and output values work together to make infrastructure code reusable, readable, and easier to share across environments.

5 min read·Easy

Terraform Input Variables

Learn Terraform input variables in depth, including variable blocks, types, defaults, validation rules, tfvars files, CLI flags, environment variables, and sensitive values.

12 min read·Easy

Terraform Local Values

Learn how Terraform local values work, when to use locals instead of variables or data sources, and how to simplify repetitive expressions in your infrastructure code.

8 min read·Easy

Explore Related Topics

AW

AWS Tutorials

Provision AWS infrastructure with Terraform

CI

CI/CD Tutorials

Run terraform plan/apply in CI pipelines

Try the Tool

YAML Validator

Validate Terraform and Kubernetes YAML configs before applying.

On This Page

What Are Output Values in Terraform?Why Output Values Matter1. Better usability2. Module communication3. Automation4. Documentation through codeDeclaring Output Values with `output` BlocksCommon arguments in an output blockSimple Output ExamplesResource attribute outputURL outputList outputMap outputA Realistic ExampleSensitive OutputsVery important warningUsing the `terraform output` CommandShow all outputsShow a specific outputUse `-json` for machine-readable outputOutput command examples in practiceFetch a load balancer URL for testingSave all outputs for another toolRead a single output cleanly in shell automationPassing Outputs Between ModulesChild module exampleRoot module using those outputsWhy outputs matter in module designUsing Outputs in CI/CD ScriptsExample scenario: DNS or app endpointExample scenario: Kubernetes bootstrapBest Practices for Output Values1. Output what is useful, not everything2. Always add descriptions3. Mark secrets as sensitive4. Prefer stable, meaningful outputs5. Think of outputs as a module APICommon Beginner MistakesOutputting values that should stay internalForgetting to mark secrets as sensitiveAssuming sensitive outputs are fully secureCreating outputs but never using themA Full Example: Outputs for a Web StackFinal ThoughtsKnowledge Check