---
description: >-
  Import and manage existing resources with OpenTofu using configuration-driven import.
---

# Import

:::warning Experimental
While we do not expect to make backwards-incompatible changes to syntax, the `-generate-config-out` flag and how OpenTofu processes imports during the plan stage and generates configuration may change in future releases.
:::

Use the `import` block to import existing infrastructure objects into OpenTofu, bringing them under OpenTofu's management. Unlike the `tofu import` command, configuration-driven import using `import` blocks is predictable, works with CICD pipelines, and lets you preview an import operation before modifying state.

Once imported, OpenTofu tracks the object as a resource instance in your state file. You can then manage the imported object like any other, updating its attributes and destroying it as part of a standard resource lifecycle.

The `import` block represents that OpenTofu imported the object and did not create it. After importing, you can optionally remove import blocks from your configuration or leave them as a record of the object's origin.

## Syntax

You can add an `import` block to any OpenTofu configuration file. A common pattern is to create an `imports.tf` file, or to place each `import` block beside the `resource` block it imports into.

```hcl
import {
  identity = {
    id = "i-abcd1234"
  }
  to = aws_instance.example
}

resource "aws_instance" "example" {
  name = "hashi"
  # (other resource arguments...)
}
```

The above `import` block defines an import of the AWS instance with the ID "i-abcd1234" into the `aws_instance.example` resource in the root module.

The `import` block has the following arguments:
- Either `identity` or `id` - To [specify which remote object to import](#import-id).
- `to` - The resource instance address that OpenTofu will use to track this object in [OpenTofu state](../state/index.mdx).
- `provider` (optional) - The provider instance to use for importing, as with [The Resource provider Meta-Argument](../../language/meta-arguments/resource-provider.mdx).
- `for_each` (optional) - Import several objects as multiple instances of the same resource by iterating over a map or a set. See [Importing multiple resources](#importing-multiple-resources) below.

If you do not set the `provider` argument, OpenTofu attempts to import from the default provider.

### Specifying what to import {#import-id}

The `identity` and `id` arguments offer two different ways to specify which remote object you intend to import. These arguments are mutually-exclusive.

The `identity` argument is the modern approach which specifies the remote object by specifying one or more attributes whose names and types vary depending on the resource type's _identity schema_. For example, importing into an `aws_instance` resource instance requires an object with a single `id` attribute:

```hcl
import {
  identity = {
    id = "i-abcd1234"
  }
  to = aws_instance.example
}
```

Not all resource types have been updated to support `identity` yet. For older resource types you must use the top-level `id` argument instead and specify the remote object using a single string in whatever form the provider is expecting. For example, `aws_instance` expects the instance ID directly when using this legacy approach:

```hcl
import {
  id = "i-abcd1234"
  to = aws_instance.example
}
```

Refer to the documentation for the resource type you are importing into to learn whether that resource type has an identity schema to use with `identity`, or if it still requires you to use the legacy `id` argument.

## Plan and apply an import

OpenTofu processes the `import` block during the plan stage. Once a plan is approved, OpenTofu imports the object into its state during the subsequent apply stage.

To import an object using `import` blocks, you must:
1. Write `import` blocks describing the relationship between the remote objects and the resource instance addresses OpenTofu should use to track them.
1. Add the corresponding `resource` blocks to your configuration , or [generate initial configuration automatically](../../language/import/generating-configuration.mdx).
1. Run `tofu plan` to review how OpenTofu will import the objects.
1. Apply the plan to import the objects and update your OpenTofu state.

An `import` block is active only if OpenTofu is not already tracking an object with the address given in `to`. After importing is successful, an `import` block becomes inert and you can optionally remove it from your configuration or retain it as a historical record for future maintainers. For more information on maintaining configurations over time, refer to [Refactoring](../../language/modules/develop/refactoring.mdx)

## Resource configuration

Before importing, you must add a `resource` block for every object (or collection of related objects) you want OpenTofu to import. Otherwise, OpenTofu raises an error during planning, insisting you add resource configuration before it can successfully import. You can create resource configuration manually or [generate it using OpenTofu](../../language/import/generating-configuration.mdx).

We recommend writing a `resource` block if you know what most of the [resource's arguments](../../language/resources/syntax.mdx#resource-arguments) will be. For example, your configuration may already contain a similar resource whose configuration you can copy and modify.

We recommend [generating configuration](../../language/import/generating-configuration.mdx) when importing multiple objects or a single complex object that you do not already have the configuration for.

### Add a `resource` block

Add a `resource` block for the resource to import into. The `to` argument in the `import` block must refer to that resource.

```hcl
import {
  to = aws_instance.example
  id = "i-abcd1234"
}

resource "aws_instance" "example" {
  name = "renderer"
}
```

### Generate configuration

OpenTofu can generate `resource` blocks for resources that are not already declared in your configuration.
For more details, refer to [Generating Configuration](../../language/import/generating-configuration.mdx).

## Examples

The following example demonstrates how to import into a module.

```hcl
import {
  to = module.instances.aws_instance.example
  id = "i-abcd1234"
}
```

The below example shows how to import a resource that includes [`count`](../../language/meta-arguments/count.mdx).

```hcl
import {
  to = aws_instance.example[0]
  id = "i-abcd1234"
}
```


The below example shows how to import a resource that includes [`for_each`](../../language/meta-arguments/for_each.mdx).
```hcl
import {
  to = aws_instance.example["foo"]
  id = "i-abcd1234"
}
```

Finally, the below example demonstrates how to import from a custom resource provider.

```hcl
provider "aws" {
  alias = "europe"
  region = "eu-west-1"
}

import {
  provider = aws.europe
  to = aws_instance.example["foo"]
  id = "i-abcd1234"
}
```

### Importing multiple objects {#importing-multiple-resources}

You can import multiple resources instances with one import block by using a `for_each` expression. This expression accepts [a set, a tuple or a map](../../language/expressions/types.mdx) and provides the `each.key` and `each.value` variables to access the individual elements.

In the example below, you can specify a list of server IDs to be imported. If you specify an empty list, the `random_id` resource will generate all IDs randomly. If you specify some IDs, the import block will import the specified IDs and the resource will randomly generate the rest. Note, the `random_id` resource requires the IDs to be in base64 format.

```
variable "server_ids" {
  type = list(string)
}

resource "random_id" "test_id" {
  byte_length = 8
  count = 2
}

import {
  to = random_id.test_id[tonumber(each.key)]
  id = each.value
  for_each = {
    for idx, item in var.server_ids: idx => item
  }
}

output "id" {
  value = random_id.test_id.*.b64_url
}
```

:::note

[Generating configuration](../../language/import/generating-configuration.mdx) is currently not possible when using `for_each` on `import` blocks.

:::