> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/infrastructure-as-code-management/use-iacm/remote-backends/use-backends.md).

# Use Existing Remote State

Harness IaCM lets you reuse existing remote state backends, such as **AWS S3**, **Google Cloud Storage (GCS)**, or **Azure Blob Storage**, without migrating to Harness-managed storage. Just point your `backends.tf` file to your existing backend, and Harness will use it directly with OpenTofu.

This approach is ideal if you are onboarding to IaCM, already use remote backends, or need compatibility with other systems or CI pipelines.

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* Your repository contains a valid `backends.tf` file.
* Your existing remote state file (for example, `.tfstate`) is accessible and versioned.
* Harness has read/write access to the remote backend. Go to [Set environment variables](/infrastructure-as-code-management/use-iacm/remote-backends/init-configuration.md#set-environment-variables) to configure access.
* You use the [Plan and Apply steps](/infrastructure-as-code-management/platform/workspaces/provision-workspace.md) in your pipeline, not custom script steps.
* Backend authentication credentials (for example, for GCS, S3, Azure) are configured via environment variables in the Harness Workspace.

### Example backends <a href="#example-backends" id="example-backends"></a>

{% tabs %}
{% tab title="AWS S3" %}

```hcl
terraform {
  backend "s3" {
    bucket         = "my-existing-tfstate-bucket"
    key            = "envs/dev/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}
```

> Ensure your Harness AWS connector or environment variables grant permission to access the bucket and DynamoDB table. [OpenTofu S3 Backend Docs](https://opentofu.org/docs/language/settings/backends/s3/)
> {% endtab %}

{% tab title="GCP Cloud Storage" %}

```hcl
terraform {
  backend "gcs" {
    bucket = "my-tfstate-bucket"
    prefix = "envs/dev"
  }
}
```

> Your GCP connector or Workspace-level environment variables must include the necessary IAM roles (for example, `roles/storage.objectAdmin`). [OpenTofu GCS Backend Docs](https://opentofu.org/docs/language/settings/backends/gcs/)
> {% endtab %}

{% tab title="Azure Blob Storage" %}

```hcl
terraform {
  backend "azurerm" {
    resource_group_name  = "tf-state"
    storage_account_name = "tfstateaccount"
    container_name       = "tfstate"
    key                  = "terraform.tfstate"
  }
}
```

> Configure access to Azure backend using environment variables like `ARM_CLIENT_ID`, `ARM_CLIENT_SECRET`, and others. [OpenTofu AzureRM Backend Docs](https://opentofu.org/docs/language/settings/backends/azurerm/)
> {% endtab %}
> {% endtabs %}

### Configure and test your pipeline <a href="#configure-and-test-your-pipeline" id="configure-and-test-your-pipeline"></a>

To provision your workspace with an existing remote backend, configure your pipeline using OpenTofu steps as shown below:

```yaml
steps:
  - step:
      name: Init
      type: IACM_TOFU_INIT
      identifier: Init
  - step:
      name: Plan
      type: IACM_TOFU_PLAN
      identifier: Plan
  - step:
      name: Apply
      type: IACM_TOFU_APPLY
      identifier: Apply
```

If your workspace requires OpenTofu/Terraform variables or environment variables, [add them in your workspace settings](/infrastructure-as-code-management/platform/iacm-connectors-variables/connectors-variables.md).

If no variables are specified, Harness uses any defaults defined in the source code (for example, `variables.tf` files in your repo). Go to [Declaring variables](https://opentofu.org/docs/language/values/variables) to review how to define variables in your source code.

**To test your setup:** Run your pipeline to execute the `init`, `plan`, and `apply` steps (and any approval plugins you have configured). Go to [IaCM Setup pipeline](/infrastructure-as-code-management/new-to-iacm/get-started.md#add-a-pipeline) for the full setup pipeline.

* Check the logs during the approval or apply step to verify successful initialization of the remote backend.
* Ensure your `backends.tf` file is present in the repository connected to your workspace.

### State locking considerations <a href="#state-locking-considerations" id="state-locking-considerations"></a>

Each remote backend implements its own locking mechanism:

* **S3** uses DynamoDB for locking.
* **GCS** relies on object metadata.
* **Azure Blob** uses blob leases.

OpenTofu handles lock acquisition and release during pipeline execution. There is **no additional locking layer in IaCM**. Locks are managed entirely by OpenTofu based on the backend settings.

### Troubleshooting and best practices <a href="#troubleshooting-and-best-practices" id="troubleshooting-and-best-practices"></a>

<details>

<summary>Error acquiring the state lock</summary>

Ensure no other process (for example, a local OpenTofu/Terraform CLI run) is holding a lock. Lock retries are handled automatically by OpenTofu/Terraform.

</details>

<details>

<summary>Plan step fails with missing or unexpected state</summary>

Confirm that the \`key\` or \`prefix\` in your \`backends.tf\` file matches the correct path in your remote backend. If you recently migrated from Terraform Cloud, verify that no \`cloud {}\` block remains in your configuration.

</details>

<details>

<summary>Local CLI commands behave differently than Terraform Cloud</summary>

Harness IaCM runs plans and applies remotely through pipelines and the IaCM CLI, not via \`cloud {}\` blocks. Use the Harness CLI or pipeline executions to perform remote plan and apply operations.

</details>

<details>

<summary>Pipeline fails after local testing with a temporary backend</summary>

If you created a local \`backend.tf\` for inspection, add it to \`.gitignore\` or remove it before running your pipeline. A committed local backend configuration overrides the workspace-managed backend during remote execution.

</details>

<details>

<summary>Permission denied or backend authentication errors</summary>

Check that your Harness connector or environment variables grant full read/write access to the backend bucket, table, or storage account. Review your connector credentials and environment variables in Workspace settings.

</details>

<details>

<summary>Concurrent operations on the same state file causing corruption</summary>

Each backend handles locking independently (DynamoDB for S3, object metadata for GCS, leases for Azure Blob). Wait for existing locks to clear before retrying; Harness does not add an additional locking layer.

</details>

**Best Practices**

* Use versioned buckets or lock tables for safe collaboration.
* Keep `backends.tf` in version control, but avoid hardcoding secrets.
* Define backend credentials via environment variables in the Harness UI or Workspace settings.
* If migrating from Terraform Cloud or OpenTofu Cloud, remove any `cloud {}` blocks and rely on backend definitions instead.
* Validate that only one process accesses a given state at a time to prevent corruption.
* Run speculative plans only from pipelines to ensure consistent remote state access.
* Use workspace variables or pipeline inputs for backend paths when multiple environments share the same backend configuration.

{% hint style="info" %}
Harness Workspaces provide the same remote execution context as Terraform Cloud workspaces, with full control over backend configuration and pipeline orchestration.
{% endhint %}

### Related links <a href="#related-links" id="related-links"></a>

* [Provision a Workspace](/infrastructure-as-code-management/platform/workspaces/provision-workspace.md)
* [IaCM Best Practices](/infrastructure-as-code-management/troubleshooting-and-resources/iacm-best-practices.md)
* [OpenTofu](https://opentofu.org/)
