# Import an Existing Terraform Project

Source: https://docs.ops0.com/docs/how-to/import-terraform-project

Bring an existing Terraform project into ops0 to get deployment history, approval gates, policy checks, and team collaboration — without changing any of your Terraform code.

---

## Scenario

Your team has been running Terraform locally for the past year. You have a production VPC project in a GitHub repository and you want to move it into ops0 for deployment history, approval gates, policy checks, and team collaboration — without touching any of your existing Terraform code.

---

## Two Import Paths

| Path | When to Use |
|------|-------------|
| **From GitHub** | Code is already in a GitHub repo |
| **Upload / Paste** | Code is local, no Git yet |

---

## Part 1: Import from GitHub

### Prerequisites

- GitHub integration configured in **Settings** → **Integrations** → **GitHub**

- Repository contains valid Terraform (`.tf` files)

- Cloud integration with deploy permissions for the target account

### Create the Project and Sync from GitHub

1. Go to **IaC** → **New Project**

2. Enter a project name — match your existing project name for clarity

3. Select **Terraform** (or OpenTofu if you were using that)

4. Click **Create**

5. In the project editor, click **GitHub** in the toolbar

6. Select your repository and branch (e.g. `main`)

7. Set the path if your Terraform is in a subdirectory (e.g. `infrastructure/vpc/`)

8. Click **Sync from GitHub** — ops0 pulls all `.tf` files into the editor

9. Verify the files appear correctly in the file explorer

---

## Part 2: Configure the State Backend

**Point ops0 to your existing state file**

If you configure a new state backend path, Terraform will treat all your existing resources as new and try to create them again. You must use the exact same bucket, key, and region as your current backend.

1. Go to **Project Settings** → **Backend**

2. Select the same backend type you're currently using (S3, GCS, Azure Blob, etc.)

3. Enter the **exact** same bucket, key, and region as your existing `backend.tf`

4. Select the cloud integration with the same permissions your team was using locally

For example, if your existing `backend.tf` is:

```hcl
terraform {
  backend "s3" {
    bucket = "my-company-terraform-state"
    key    = "production/vpc/terraform.tfstate"
    region = "us-east-1"
  }
}
```

Enter those exact values in ops0. ops0 will use the existing state file — Terraform sees the existing resources as already tracked and makes no changes.

---

## Part 3: Verify with a Plan

Run a plan to confirm ops0 is reading your state correctly.

1. Click **Deploy** → **Run Plan**

2. Expected result: **0 changes** — Terraform reads the existing state and finds everything matches

3. If the plan shows unexpected creates: the state path is wrong or the credentials have different scope — double-check the backend configuration

A clean 0-change plan means ops0 is now managing your existing infrastructure correctly. Any differences shown are real drift between your code and the actual resource configuration.

---

## Part 4: Enable Team Features

Now that the project is imported, enable the ops0 features that weren't available before.

### Add team members

1. Project → **Collaborators** → **Add** → select teammates → assign Editor or Approver role

### Enable approval gates

1. Project **Settings** → enable **Require Approval** → designate an approver

### Add policies

1. **Settings** → **Policies** → create or attach policies to the project → every deploy is now checked before apply

### Connect GitHub sync for PR workflows

1. **GitHub** button → set to `main` branch → changes pushed via PR now sync back into ops0 automatically

---

## Verification

Confirm the import is complete and working:

- Plan shows **0 changes** after import
- Project card shows correct file count and last-modified time
- Team members can see the project in their IaC list
- A test deployment (no code changes) completes successfully

---

## Troubleshooting

Plan shows all resources being created

The state backend path is wrong — ops0 is pointing to an empty or new state file. Fix the bucket, key, and region in Project Settings → Backend, then retry the plan.

Provider not configured error

Your `provider.tf` contains `profile = "default"` or similar local-only config. Remove it or replace with IAM role-based auth — ops0 uses the connected cloud integration, not local AWS profiles.

Syntax errors after GitHub sync

The files synced correctly but contain Terraform version-specific syntax. Check the `required_version` constraint in your code and ensure it matches ops0 (Terraform 1.5+).

State lock error

Another deployment is running, or a previous run left the lock held. If using S3 with DynamoDB locking, delete the lock item manually in DynamoDB, or wait for the other process to complete before retrying.

---

## Next Steps

[Set Up GitOps Workflow → Run plans automatically on PRs and deploy on merge](https://docs.ops0.com/docs/how-to/setup-gitops)
[Create Approval Workflows → Require human sign-off before production deployments](https://docs.ops0.com/docs/how-to/approval-workflows)
