# atmos terraform migrate

Use `atmos terraform migrate` to run user-authored `tfmigrate` migrations in an Atmos Terraform component context.

> ⚠️ Experimental

**Configure Tfmigrate Hooks**

Run migrations automatically from Terraform lifecycle hooks.

Hooks Reference[Read more](/stacks/hooks)

## Usage

```shell
atmos terraform migrate <subcommand> [component] [options]
```

Atmos prepares the component before `tfmigrate` runs. Source provisioning, workdir provisioning, generated backend files, generated varfiles, auth identity setup, and Terraform workspace selection all happen first.

## Arguments

- **`subcommand`** — Migration action to run. Supported values are `plan`, `apply`, and `list`.
- **`component`** — Atmos Terraform component to migrate or inspect. Omit when selecting multiple components with flags such as `--all`, `--components`, `--query`, or (for `plan` and `apply`) `--affected`.

## Flags

- **`--stack` / `-s`** — Atmos stack where the component is defined.
- **`--identity` / `-i`** — Identity to authenticate before resolving the component and running `tfmigrate`. Environment variable: `ATMOS_IDENTITY`.
- **`--migration`** — A single `tfmigrate` migration file for `plan` or `apply`. `tfmigrate` resolves the value relative to the `migration_dir` set in its config (default `.`). Pass just the filename when `migration_dir` already points at your migrations directory. Omit this flag to let `tfmigrate` run history mode.
- **`--tfmigrate-config`** — Override the `tfmigrate` config path. Atmos checks, in order: this flag or `ATMOS_TFMIGRATE_CONFIG`, then `TFMIGRATE_CONFIG`, then a `.tfmigrate.hcl` file in the component. When none of these are set, Atmos generates a config that reuses the component's Terraform backend as history storage.
- **`--backend-config`** — Backend config entry passed to `tfmigrate --backend-config`. Repeat the flag for multiple entries.
- **`--all`, `--components`, `--query`, `--affected`** — Select multiple Terraform component instances instead of passing one component argument. `--affected` applies to `plan` and `apply` only. `list` supports `--all`, `--components`, and `--query`.
- **`--skip-init`** — Skip the normal Terraform init path before `tfmigrate` runs.

## Authentication

`atmos terraform migrate` uses the same identity flow as other Terraform commands. Pass an identity explicitly when the migration needs cloud credentials for backend access, YAML functions, source provisioning, or `tfmigrate` history storage:

```shell
atmos terraform migrate plan s3-bucket -s plat-ue2-dev --identity aws-prod --tfmigrate-config .tfmigrate.hcl
```

You can also use `ATMOS_IDENTITY`:

```shell
ATMOS_IDENTITY=aws-prod atmos terraform migrate apply s3-bucket -s plat-ue2-dev --tfmigrate-config .tfmigrate.hcl
```

When no identity is provided, Atmos can use the component or stack default identity. Use `--identity` without a value to select interactively, or `--identity=false` to disable authentication for the command.

## Subcommands

## Examples

Preview history-mode migrations:

```shell
atmos terraform migrate plan s3-bucket -s plat-ue2-dev
```

Apply history-mode migrations:

```shell
atmos terraform migrate apply s3-bucket -s plat-ue2-dev
```

List migration context and history settings:

```shell
atmos terraform migrate list -s plat-ue2-dev
```

## How Atmos Runs `tfmigrate`

For every selected component instance, Atmos:

- Resolves the stack/component with the standard Terraform command flags.
- Authenticates the configured Atmos identity before migration.
- Runs the normal Terraform init path unless `--skip-init` is set.
- Selects the configured Terraform workspace.
- Resolves `tfmigrate` and Terraform/OpenTofu through the Atmos toolchain or PATH.
- Sets `TFMIGRATE_EXEC_PATH` to the resolved Terraform/OpenTofu binary unless already set.
- Routes the generated varfile into `tfmigrate`'s internal Terraform plans via `TF_CLI_ARGS_plan`. This lets components with required variables plan cleanly.
- Generates a default `tfmigrate` config when you have not provided one. The default reuses the component's Terraform backend as history storage.
- Pre-creates the parent directory of a `storage "local"` history path from the `tfmigrate` config. This prevents the first history save from failing on a missing directory.
- Exports per-instance history helper variables for the `tfmigrate` config.

## History Mode

Enable `tfmigrate` history mode by omitting `--migration`:

```shell
atmos terraform migrate apply s3-bucket -s plat-ue2-dev
```

History storage works with zero configuration. When the component has no `.tfmigrate.hcl`, and no `--tfmigrate-config` or `TFMIGRATE_CONFIG`, Atmos generates a `tfmigrate` config that reuses the component's Terraform backend:

- **S3 backend** — Atmos stores history in the same bucket, under `tfmigrate/<stack>/<component>/<workspace>/history.json`. It inherits the region, profile, assume-role ARN, KMS key, and custom endpoint.
- **GCS backend** — Atmos stores history in the same bucket, under the same namespaced object name.
- **Local or other backends** — Atmos stores history as a local file next to the local-backend state file, or under the component working directory. Atmos creates the directory automatically.

The generated config points `migration_dir` at the component's `migrations/` directory when one exists, the component root otherwise.

To take control, add a `.tfmigrate.hcl` file to the component, or point at one explicitly. Atmos discovers a component-local file automatically, and skips the generated default entirely:

```shell
atmos terraform migrate apply s3-bucket -s plat-ue2-dev --tfmigrate-config migrations/.tfmigrate.hcl
```

## History Variables

Atmos sets these variables for use from the `tfmigrate` config via `env`:

- **`ATMOS_STACK`** — The selected Atmos stack.
- **`ATMOS_COMPONENT`** — The selected Terraform component instance.
- **`ATMOS_TERRAFORM_WORKSPACE`** — The selected Terraform workspace, or `default` when none is configured.
- **`ATMOS_TFMIGRATE_HISTORY_NAMESPACE`** — `tfmigrate/&lt;stack&gt;/&lt;component&gt;/&lt;workspace&gt;`.
- **`ATMOS_TFMIGRATE_HISTORY_KEY`** — `tfmigrate/&lt;stack&gt;/&lt;component&gt;/&lt;workspace&gt;/history.json`.
- **`ATMOS_TFMIGRATE_HISTORY_BUCKET`** — Copied from the component Terraform backend when the backend is S3 or GCS.
- **`ATMOS_TFMIGRATE_HISTORY_REGION`, `ATMOS_TFMIGRATE_HISTORY_PROFILE`, `ATMOS_TFMIGRATE_HISTORY_ROLE_ARN`** — Copied from supported S3 backend settings.

Atmos namespaces the history key by stack, component, and workspace. This avoids collisions when multiple Atmos component instances share the same Terraform backend bucket.

## Rerun Safety

Single-file `tfmigrate apply path.hcl` is not inherently idempotent. A rerun can fail if a `state mv` source or `state rm` address already changed.

For CI, use `tfmigrate` history mode with durable storage such as S3, GCS, or a local file persisted by the workflow runner.

## Related

- [`atmos terraform migrate plan`](/cli/commands/terraform/migrate-plan)
- [`atmos terraform migrate apply`](/cli/commands/terraform/migrate-apply)
- [`atmos terraform migrate list`](/cli/commands/terraform/migrate-list)
- [Hooks](/stacks/hooks)
- [Terraform Component Configuration](/cli/configuration/components/terraform)

## Try it out

### hooks-tfmigrate

Copy the example into a new directory and make it your own:

```shell
atmos init examples/hooks-tfmigrate
cd hooks-tfmigrate
```

List the checked-in tfmigrate migrations for the service component. Follow the README before applying its state migration.

```shell
atmos terraform migrate list service -s test
```

- [Installation guide](/install)
- [Explore the example](/examples/hooks-tfmigrate)
- [Initialization and repository settings](/cli/commands/init#examples-and-source-directories)
