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".