---
description: Output values are the return values of a module.
---

# Output Values

Output values make information about your infrastructure available on the
command line, and can expose information for other OpenTofu configurations to
use. Output values are similar to return values in programming languages.

Output values have several uses:

- A child module can use outputs to expose a subset of its resource attributes
  to a parent module.
- A root module can use outputs to print certain values in the CLI output after
  running `tofu apply`.
- When using [remote state](../../language/state/remote.mdx), root module outputs can be
  accessed by other configurations via a
  [`terraform_remote_state` data source](../../language/state/remote-state-data.mdx).

Resource instances managed by OpenTofu each export attributes whose values
can be used elsewhere in configuration. Output values are a way to expose some
of that information to the user of your module.

:::note
For brevity, output values are often referred to as just "outputs"
when the meaning is clear from context.
:::

## Declaring an Output Value

Each output value exported by a module must be declared using an `output`
block:

```hcl
output "instance_ip_addr" {
  value = aws_instance.server.private_ip
}
```

The label immediately after the `output` keyword is the name, which must be a
valid [identifier](../../language/syntax/configuration.mdx#identifiers). In a root module, this name is
displayed to the user; in a child module, it can be used to access the output's
value.

The `value` argument takes an [expression](../../language/expressions/index.mdx)
whose result is to be returned to the user. In this example, the expression
refers to the `private_ip` attribute exposed by an `aws_instance` resource
defined elsewhere in this module (not shown). Any valid expression is allowed
as an output value.

:::note
Outputs are only rendered when OpenTofu applies your plan. Running
`tofu plan` will not render outputs.
:::

## Accessing Child Module Outputs

In a parent module, outputs of child modules are available in expressions as
`module.<MODULE NAME>.<OUTPUT NAME>`. For example, if a child module named
`web_server` declared an output named `instance_ip_addr`, you could access that
value as `module.web_server.instance_ip_addr`.


## Custom Condition Checks

You can use `precondition` blocks to specify guarantees about output data. The following examples creates a precondition that checks whether the EC2 instance has an encrypted root volume.

```hcl
output "api_base_url" {
  value = "https://${aws_instance.example.private_dns}:8433/"

  # The EC2 instance must have an encrypted root volume.
  precondition {
    condition     = data.aws_ebs_volume.example.encrypted
    error_message = "The server's root volume is not encrypted."
  }
}
```

Custom conditions can help capture assumptions, helping future maintainers understand the configuration design and intent. They also return useful information about errors earlier and in context, helping consumers more easily diagnose issues in their configurations.

Refer to [Custom Condition Checks](../../language/expressions/custom-conditions.mdx#preconditions-and-postconditions) for more details.

## Optional Arguments

`output` blocks can optionally include `description`, `sensitive`, `ephemeral` and `depends_on` arguments, which are described in the following sections.

<a id="description"></a>

### `description` — Output Value Documentation

Because the output values of a module are part of its user interface, you can
briefly describe the purpose of each value using the optional `description`
argument:

```hcl
output "instance_ip_addr" {
  value       = aws_instance.server.private_ip
  description = "The private IP address of the main server instance."
}
```

The description should concisely explain the
purpose of the output and what kind of value is expected. This description
string might be included in documentation about the module, and so it should be
written from the perspective of the user of the module rather than its
maintainer. For commentary for module maintainers, use comments.

<a id="sensitive"></a>

### `sensitive` — Suppressing Values in CLI Output

An output can be marked as containing sensitive material using the optional
`sensitive` argument:

```hcl
output "db_password" {
  value       = aws_db_instance.db.password
  description = "The password for logging in to the database."
  sensitive   = true
}
```

OpenTofu will hide values marked as sensitive in the messages from
`tofu plan` and `tofu apply`. In the following scenario, our root
module has an output declared as sensitive and a module call with a
sensitive output, which we then use in a resource attribute.

```hcl
# main.tf

module "foo" {
  source = "./mod"
}

resource "test_instance" "x" {
  some_attribute = module.foo.a # resource attribute references a sensitive output
}

output "out" {
  value     = "xyz"
  sensitive = true
}

# mod/main.tf, our module containing a sensitive output

output "a" {
  value     = "secret"
  sensitive = true
}
```

When we run a plan or apply, the sensitive value is redacted from output:

```
OpenTofu will perform the following actions:

  # test_instance.x will be created
  + resource "test_instance" "x" {
      + some_attribute    = (sensitive value)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + out = (sensitive value)
```

OpenTofu will still record sensitive values in the [state](../../language/state/index.mdx),
and so anyone who can access the state data will have access to the sensitive
values in cleartext. For more information, see
[_Sensitive Data in State_](../../language/state/sensitive-data.mdx).

<a id="ephemerality"></a>

### `ephemeral` — Control what outputs can be stored to state and plan

An output can be marked as ephemeral using the optional
`ephemeral` argument:

```hcl
output "db_password" {
  value       = aws_db_instance.db.password
  description = "The password for logging in to the database."
  ephemeral   = true
}
```

By configuring an `output` block with the `ephemeral` attribute, the module author will limit its usage
only to the allowed ephemeral contexts:
* [Ephemeral Resources](../ephemerality/ephemeral-resources.mdx)
* [Ephemeral Variables](../values/variables.mdx#ephemerality)
* [Ephemeral Outputs](../values/outputs.mdx#ephemerality)
* [Locals](../values/locals.mdx#ephemerality)
* [Providers](../providers/configuration.mdx)
* [Provisioners](../resources/provisioners/syntax.mdx#suppressing-provisioner-logs-in-cli-output)
* [Resource `connection` blocks](../resources/provisioners/connection.mdx#ephemeral-usage)
* [Resource `write-only` attributes](../ephemerality/write-only-attributes.mdx)

:::note
A root module `output` block cannot be configured with such an attribute. This is a configuration intended only for child modules.
:::

```hcl
# main.tf

module "foo" {
  source = "./mod"
}

resource "test_instance" "x" {
  secret_wo = module.foo.a # the "secret_wo", which is a write only attribute configured by the "test_instance" managed resource can reference this
}

# mod/main.tf, our module containing a sensitive output

output "a" {
  value     = "secret"
  ephemeral = true
}
```

When we run a plan or apply, the value used in the `resource` block is suppressed from the output:

```
OpenTofu will perform the following actions:

  # test_instance.x will be created
  + resource "test_instance" "x" {
      + secret_wo = (write-only attribute)
    }

Plan: 1 to add, 0 to change, 0 to destroy.
```
<a id="depends_on"></a>

### `depends_on` — Explicit Output Dependencies

Since output values are just a means for passing data out of a module, it is
usually not necessary to worry about their relationships with other nodes in
the dependency graph.

However, when a parent module accesses an output value exported by one of its
child modules, the dependencies of that output value allow OpenTofu to
correctly determine the dependencies between resources defined in different
modules.

Just as with
[resource dependencies](../../language/resources/behavior.mdx#resource-dependencies),
OpenTofu analyzes the `value` expression for an output value and automatically
determines a set of dependencies, but in less-common cases there are
dependencies that cannot be recognized implicitly. In these rare cases, the
`depends_on` argument can be used to create additional explicit dependencies:

```hcl
output "instance_ip_addr" {
  value       = aws_instance.server.private_ip
  description = "The private IP address of the main server instance."

  depends_on = [
    # Security group rule must be created before this IP address could
    # actually be used, otherwise the services will be unreachable.
    aws_security_group_rule.local_access,
  ]
}
```

The `depends_on` argument should be used only as a last resort. When using it,
always include a comment explaining why it is being used, to help future
maintainers understand the purpose of the additional dependency.

<a id="deprecated"></a>

### `deprecated` — Marking output as deprecated

The `deprecated` argument in a module output block indicates its deprecation and potential
removal in the future. This attribute should contain non-empty string and should provide
instructions on how to migrate away from usage of this module output. Here is an example of
the configuration:

```hcl
output "examle" {
  value      = "someval"
  deprecated = "'examle' output must no longer be used due to a typo, use 'example' instead"
}
```

The caller of the module will receive a warning if the deprecated output is referenced in
their configuration:

```
Warning: Value derived from a deprecated source

  on main.tf line 45, in locals:
  45:   a = module.mod.examle

This value is derived from module.mod.examle, which is deprecated with the following message:

'examle' output must no longer be used due to a typo, use 'example' instead
```

Deprecation warnings can be filtered or disabled by using the `-deprecation` CLI argument.
By default, deprecated module outputs will be consolidated by the output address. In
order to see them individually, `-consolidation-warnings=false` can be used.
For more details, check its description in the command options for
[plan](../../cli/commands/plan.mdx#other-options) and [apply](../../cli/commands/apply.mdx#apply-options).
