Terraform outputs.tf Generator

Generate outputs.tf from what a module creates. The finding to read first is about sensitivity: an output prints its value at the end of every apply unless you say otherwise.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Generate. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

A database taking a password

Any output derived from this needs sensitive = true, because outputs print by default

resource "aws_db_instance" "main" {
  identifier = "main"
  password   = var.db_password
}

A resource with for_each

A map, not a single value, so the output has to preserve the keys

resource "aws_subnet" "private" {
  for_each = var.subnets
  vpc_id   = var.vpc_id
}

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Outputting a password without marking it sensitive

    Terraform prints every output at the end of the apply and terraform output shows it on request. The CI log then holds it permanently.

    Instead:Add sensitive = true, and consider not outputting it at all if the consumer can read it from a secret manager.

  2. Outputting everything a module creates

    Every output is part of the module's public interface, and removing one later is a breaking change for callers you cannot see.

    Instead:Output what callers actually need. Add more when somebody asks.

  3. Referencing a for_each resource without a key

    The resource is a map, so a bare .id does not exist and the error names the resource rather than the collection type.

    Instead:Use a for expression that preserves the keys: { for k, v in aws_subnet.private : k => v.id }.

An output is not sensitive unless you mark it

Terraform prints every output at the end of an apply, terraform output shows them on demand, and CI keeps the log. None of that changes because the value happens to be a password.

sensitive = true is opt-in, on every output

Where the value came from something already marked sensitive, Terraform refuses the output rather than printing it, which is the good outcome and the one people rely on without realising. Where the value came from an attribute the provider does not mark, such as a connection string you assembled, it just prints. Mark it yourself.

The best answer is often not to output it at all

An output is a public interface. If a consumer can read the value from a secret manager instead, that is fewer copies in fewer logs, and the consumer gets access audited by something built for it.

Every output is part of the module's contract

Removing one is a breaking change for whoever reads it, and you cannot see who that is from inside the module. A short, deliberate output list is a feature, not laziness, which is why this page generates candidates rather than a finished file.

An expanded resource is not a single value

With for_each the resource is a map, so a bare .id does not exist; a for expression over it keeps the keys, which is almost always what a consumer wants. With count it is a list and needs a splat, and the list order follows the count index, so it shifts when the collection changes in the middle.

Module outputs do not travel upwards

A module's output is visible to its caller and no further. Three levels of nesting means declaring the same value three times, which is tedious and is the design: a module boundary is meant to be deliberate rather than transparent.

The description is the module's documentation

It is what terraform-docs publishes, whether or not anybody wrote it, so an empty one produces a table with a blank column. Say what the value is for rather than what it is: "pass to the app's DATABASE_URL" beats "the endpoint".

More terraform tools

Terraform Validator & Formatter Does it parse, and is it formatted? Terraform dynamic Block Generator It is ingress.value, not each.value Terraform check and precondition Generator A failed check does not stop the apply Terraform variables.tf Generator From the var. references you already wrote Terraform Unused Declaration Linter Dead variables, locals and data sources Terraform Atlantis YAML Generator when_modified misses your modules Terraform Function Tester and HCL Console terraform console, in a tab Terraform for Expression Tester Where do the keys collide? Terraform Interpolation Tester null becomes an empty string Terraform templatefile Tester Render it before you apply it Terraform Resource Count Calculator How many objects, not how many blocks Terraform count to for_each Converter With the moved blocks it needs Terraform moved Block Generator Rename without destroying Terraform state mv Command Builder No plan, no undo Terraform target Flag Builder And why to stop using it Terraform Remote State Data Source Generator It grants read of the whole state Terraform Provider Block Generator docker is not hashicorp/docker Terraform .gitignore Generator and Checker .terraform* eats the lock file Terraform to OpenTofu Migration Checker The state is the part to watch Terraform tfvars to JSON Converter The JSON file wins Terraform Version Constraint Parser What ~> actually allows Terraform Resource Address Parser Quote it before the shell eats it Terraform cidrsubnet Calculator newbits is added, not the target Terraform Import Block Generator The id is not the name Terraform Lock File Viewer Why CI fails and your laptop does not Terraform Variables Checker A missing value hangs CI Terraform tfvars to Env Vars Converter Lists and maps have to be JSON Terraform Deprecated Syntax Checker What a current Terraform rejects Terraform State File Viewer Read it without uploading it Terraform Plan JSON Viewer It is not redacted Terraform HCL to JSON Converter And what the conversion loses Terraform Module Source Validator version only works for the registry Terraform Backend Config Decoder Is state actually locked? Terraform Naming Convention Validator A hyphen makes a resource unreferenceable

Elsewhere on the site