---
description: >-
  A terraform_data managed resource allows you to configure provisioners that
  are not directly associated with a single existing resource.
---

# Provisioners Without a Resource

If you need to run provisioners that aren't directly associated with a specific
resource, you can associate them with a `terraform_data`.

Instances of [`terraform_data`](../../../language/resources/tf-data.mdx) are treated
like normal resources, but they don't do anything. Like with any other resource
type, you can configure [provisioners](../../../language/resources/provisioners/syntax.mdx)
and [connection details](../../../language/resources/provisioners/connection.mdx) on a
`terraform_data` resource. You can also use its `input` argument, `triggers_replace` argument, and any
meta-arguments to control exactly where in the dependency graph its
provisioners will run.

:::warning Important
Use provisioners as a last resort. There are better alternatives for most situations. Refer to
[Declaring Provisioners](../../../language/resources/provisioners/syntax.mdx) for more details.
:::

## Example usage

```hcl
resource "aws_instance" "cluster" {
  count = 3

  # ...
}

resource "terraform_data" "cluster" {
  # Replacement of any instance of the cluster requires re-provisioning
  triggers_replace = aws_instance.cluster.[*].id

  # Bootstrap script can run on any instance of the cluster
  # So we just choose the first in this case
  connection {
    host = aws_instance.cluster.[0].public_ip
  }

  provisioner "remote-exec" {
    # Bootstrap script called with private_ip of each node in the cluster
    inline = [
      "bootstrap-cluster.sh ${join(" ", aws_instance.cluster.*.private_ip)}",
    ]
  }
}
```
