Switch from Terraform Cloud in Minutes with Our New Migration Tool
Tags: terraform, devops, cloudcomputing, infrastructureascode
Published: 2024-03-11 16:07:27

Vendor lock-in is an important consideration when evaluating any technology. It's great when a tool or service is a perfect fit for your requirements, but over time product features, pricing models or your needs may change. 

When that happens, you want to be sure that you can migrate to a new platform with minimal effort and zero impact. The newly released migration tool from env0 makes the migration process from [Terraform Cloud](https://www.env0.com/blog/terraform-cloud) to env0 simple, quick, and convenient.

**Why migrate from Terraform Cloud?**
-------------------------------------

[Terraform Cloud](https://www.env0.com/blog/terraform-cloud) is a Terraform automation platform offered by HashiCorp. It's an excellent service with a broad swath of happy users. 

That being said, products and requirements change over time resulting in a mismatch of product and customer. Here are a few reasons we've heard of customers considering a migration:

1.  The Resources Under Management (RUM) pricing has driven up costs for the platform.
2.  The [BSL license change](https://www.env0.com/blog/hashicorp-license-change) caused uncertainty and some would like to stick with an open-source tool.
3.  There are new business requirements that are not met by the platform.

While it's not necessarily the main decision factor, the most common reason at the moment is the new RUM pricing model. 

While it may work out advantageously for some organizations, others are structured in a way where the new pricing model causes costs to balloon. You can find a detailed analysis of [Terraform Cloud pricing here](https://www.env0.com/blog/terraform-cloud-pricing-a-complete-guide).

Ultimately, if Terraform Cloud is working for you, then we are not suggesting that you migrate just for kicks. But if you find yourself looking to migrate off Terraform Cloud,  the new env0 migration tool can make it easier for you and assist with moving your workspaces, including state and variables to env0.

If you have more than a handful of workspaces in Terraform Cloud, migrating them to another platform manually is a time-consuming and error-prone process. 

At a minimum, you need to create workspaces on the destination platform, copy over the settings and input variable values, and migrate the state data. That’s a daunting task to perform at scale, and so the env0 team created a migration tool to simplify and automate the migration process, reducing what could be days of tedious work to a few minutes of running scripts.

**Getting started with the env0 migration tool**
------------------------------------------------


{% vimeo 914333936 %}‍

Born out of frequent customer requests, the migration tool simplifies and accelerates the transfer from Terraform Cloud to env0, at any scale.

The tool is an [open-source project available on GitHub](https://github.com/env0/env0-migration-tool/tree/main/TFC). It is intended to migrate the contents of a Terraform Cloud workspace to an environment in env0, including the following:

*   Project placement
*   VCS repository settings
*   Terraform version value
*   Variable values
*   State data

The tool currently supports version control system (VCS) backed workspaces and will select OpenTofu on env0 if the workspace Terraform version on Terraform Cloud is 1.6 or newer.

### **Migration process**

The migration process consists of a few simple stages: preparing your local machine, exporting Terraform Cloud workspace settings, and creating environments in env0.

The tool follows the process outlined below:

1.  Prepare your local machine
2.  Export Terraform Cloud workspace settings
3.  Create environment in env0 with exported settings
4.  Copy state data from workspace to environment

You can migrate multiple Terraform Cloud workspaces at the same time and filter using tags. Let's walk through the process with some example workspaces in Terraform Cloud!

**Note:** The details of the migration process may change over time, refer to the **README.md** file in the GitHub repository for step-by-step instructions.

### **Prepare for Migration**

On my local machine, I’ve cloned the GitHub repository containing the migration tool to a local directory. I’ve also procured API tokens from both [Terraform Cloud](https://app.terraform.io/app/settings/tokens) and [env0](https://docs.env0.com/reference/authentication#creating-a-personal-api-key).

![env0 migration tool](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d21f07f7710714027adf62_2UR05uJzh5VN0P3Q2Ed6w59MBfp5d-RTDxZbOkEodxOWOzfIoz6Pxc3wepGYY5H_Ve9H_O9Xl9S6GU0zWUHm1EjCUYgz4SvYzWFEZaLaDGX75I8ZWgt4xTT-rLprudjhaqcjuX-aK4F1nQmnpL2Jya8.png)

On Terraform Cloud, I have three workspaces in a project called `env0-migration-example`.

![a screen showing TFC workspaces](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d21f07960ab49fbbae9959_dHlZX2KRt71hreDn2rxYm5rb1pz0P_MwQ482n95q74e3q3n97h2JdAcKj9J2NKpTetu6t_OqTiOnzcxEmi-cw32pDv3_lBRX8hwKtyYHfxq5YwK9FMpSbixbrGp6nyfq3KZGj_ETnd15p2Ai_Tkxcz8.png)

These are the workspaces we will be migrating to env0. Looking in the details of one of the workspaces, it is using the VCS workflow linked to a public GitHub repository named `tfc-azure-example`.

![a screen zooming into details of one of TFC workspaces](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d21f07ccb2aa8ee0f7008a_8YlPa4f5ax2aT7Dwhq9j3pAp-tZryfcR9rhqKWVx4fte4u4d0sS2d6EZ4dXlk5TmGsvXaWbk4iCC-z_9jFebvMIwjqi6Q6oXUmxKn9xeOp_N5jXRUFgSHYGyDJ1KZ5CxIDW3I6hxBL2uKgbWtJVWPYU.png)

The workspace variables include a prefix value for naming and credentials for provisioning infrastructure in Azure.

![workspace variables prefix](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d21f07ec36cc22964bbda6_AC7KHdJD4pv-L_imySqtVGHJjVKLV8VLzsxwnpfIDGwusa5_-rzP0wotBkbmsx1RzhB6beQcjPqVh0noIcErvbJDiQaEwBq6U6FOKL9ohchtYgo_kkTz35S_KIwALqH-Nob8EJy97rkqfzF3SZVl50s.png)

The migration process will migrate these variable values, the state data, and the workspace to env0.

### **Export Terraform Cloud Workspaces**

Our first step is to export the Terraform Cloud workspaces we want to migrate using the Terraform configuration stored in the **TFC** directory of the cloned repository.

    $ tree TFC
    TFC
    ├── README.md
    ├── main.tf
    ├── migrate-state
    │   ├── README.md
    │   ├── env0_template
    │   ├── migrate_single_workspace.sh
    │   ├── migrate_workspaces.sh
    │   ├── tfc_template
    │   └── troubleshooting-guide.md
    ├── parse_projects.tf
    ├── parse_workspaces.tf
    ├── providers.tf
    ├── tfc_data.tf
    └── variables.tf
    

Before applying the configuration, we need to create a **tfvars** file with the following settings defined:

    # exporter.tfvars
    tfc_token = "your-tfc-token"
    tfc_organization = "your-tfc-organization"
    tfc_workspace_names = ["shared-network-*"]
    

And set the environment variable _TFE\_TOKEN_ to our Terraform Cloud API token:

    $ export TFE_TOKEN=lHk3h0yEenY8WA.atlasv1.zgGLxGx0478VFyKkqQHi4MOvYoJ5oNHW8W1i8ba...
    

Now we can initialize the Terraform configuration and apply it.

    $ terraform init
    
    Initializing the backend...
    
    Initializing provider plugins…
    
    Terraform has been successfully initialized!
    
    $ terraform apply -var-file="exporter.tfvars"
    ...
    Plan: 1 to add, 0 to change, 0 to destroy.
    
    Do you want to perform these actions?
      Terraform will perform the actions described above.
      Only 'yes' will be accepted to approve.
      Enter a value: yes
    
    local_file.data: Creating...
    local_file.data: Creation complete after 0s [id=430cf17b8fe387613802fdd5ecbd988c6af62]
    

### **Create environments in env0**

This step involves two processes.. First, we will use the Terraform code in the **env0-resources-generator** directory to create a new Terraform configuration with all necessary resources for creating environments in our env0 account.

Then we’ll use the newly created configuration to actually deploy the resources to env0.

#### **Create a Terraform configuration for env0**

From the **env0-resources-generator** directory, we will run terraform init and apply, pointing to the **data.json** file for input:

    $ terraform init
    Initializing the backend...
    Initializing provider plugins...
    Terraform has been successfully initialized!
    
    $ terraform apply -var-file=../TFC/out/data.json
    ...
    Plan: 3 to add, 0 to change, 0 to destroy.
    Do you want to perform these actions?
      Terraform will perform the actions described above.
      Only 'yes' will be accepted to approve.
    
      Enter a value: yes
    
    local_file.main: Creating...
    local_file.projects: Creating...
    local_file.environments: Creating...
    ...
    Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
    

The result is a collection of files in the **env0-resources-generator/out** directory that make up a Terraform configuration to deploy the corresponding projects and environments in env0.

    $ tree
    .
    ├── environments.tf
    ├── main.tf
    └── projects.tf
    

#### **Deploy the env0 resources**

Now that we have a configuration to deploy the necessary resources in env0, we can navigate to the **out** directory and deploy it.

Before we run [`terraform apply`](https://www.env0.com/blog/terraform-apply-guide-command-options-and-examples), we need to configure a couple environment variables to authenticate to env0:

    $ export ENV0_API_KEY=yqyox_b8rogfq
    $ export ENV0_API_SECRET=bChV5uX1feH9SA4muesySOWRnN2iafJ
    

With those environment variables set, it’s a simple matter of navigating into the **out** directory and deploying the Terraform configuration:

    $ cd out
    $ terraform init
    Initializing the backend...
    Initializing provider plugins...
    Terraform has been successfully initialized!
    $ terraform apply -auto-approve
    ...
    Plan: 4 to add, 0 to change, 0 to destroy.
    env0_project.env0-migration-example: Creating...
    env0_project.env0-migration-example: Creation complete after 4s [id=0915eb9d-88bd-4ea8-9734]
    env0_environment.shared-network-dev: Creating...
    env0_environment.shared-network-stage: Creating...
    env0_environment.shared-network-prod: Creating...
    env0_environment.shared-network-dev: Creation complete after 2s [id=3b680701-f145-478d]
    env0_environment.shared-network-prod: Creation complete after 5s [id=9652b5b5-4ebc-4813]
    env0_environment.shared-network-stage: Creation complete after 5s [id=303b19b4-bade-4279]
    
    Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
    

When the deployment completes, we’ll now have a project with three environments deployed in env0 that mirrors our workspaces in Terraform Cloud.

![environments deployed in env0](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d2219c9653c54bca070991_kVNmv0kkj0DXq2zdRXvJXno668ebhnrsrJ45J7IUGLAAx1uYbinejmZPyKdRFG5HEbl-qyFmmX2T7Bp_n9kEqrJVEw49qGX2E-sdii5EcWjWubsh2R0vvdstNYvTj7ZYsR3IJlqqRgVJ2Wcscj-qGfI.png)

Looking inside the 'Variables' section of the `shared-network-dev` environment shows that both the Terraform and Environment variables have been copied over.

![Variables in env0](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d2219c55604fbc04db237f_YM-s0v1Gykeq8HleIb2gj9MP7WkNb_x-Jg51ZDU7k-6cUWxPU_3StAoAuUB3RCooBDTLKWwko7ydE2LkLavASItblUZ4rbmzUFcQCbYELfl3xRBhubme0C9kFtO1T6U5MYwHof7oBCbwV4NGw8Tx9vE.png)

![Variables in env0](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d2219c9cb7c96fa568b0a3_-6Ahb_VD2b4itdnyAPhp8bkWAPgBItVJufrp1Jeymck-cYYbnSdAj_WSO-0lkraGMSH9VGxtAHW66LwmXCGejdr3i3HwV84lgHFu8SEazL9A1U5ya06GIQ8q4M-ViO0uLoOXrh5TjaycSKognGO_BlM.png)

Since the `ARM\_CLIENT\_SECRET` was stored as sensitive in Terraform Cloud, the migration tool uses a placeholder value of `secret\_value\_from\_terraform\_cloud`, which we need to update to the actual value.

The migration tool does not copy sensitive values to help prevent possible leakage and exposure on your local workstation. (Honestly, we should be using OIDC authentication anyway!)

Before we update the `ARM\_CLIENT\_SECRET` variable value, we still need to migrate the state data for our workspaces as well.

### **Copy state data from workspace to environment**

The state migration process uses the **migrate\_workspaces.sh** bash script found in the **TFC/migrate-state** directory.

Before we run the script, we will need to set some additional environment variables:

    $ export ENV0_ORG_ID=111111-1111-1111-1111-11111111111
    $ export TFC_ORG_NAME=your-tfc-org-name
    

The script also needs us to log into the Terraform Cloud and env0 backends using the `terraform login` command. First, we’ll generate a base64 token based on our env0 API credentials and use that value to log into the env0 backend:

    $ echo -n $ENV0_API_KEY:$ENV0_API_SECRET | base64
    eXF5b3hfYjhyb2dmcWZfZTpiQ2hWNXVYMWZlSDlTQTRtdWVzeVNPV1JuTjJpYWZKOA==
    $ terraform login backend.api.env0.com
    

Then log into Terraform Cloud using the token value stored in the `TFC\_TOKEN` environment variable:

    $ terraform login
    

Once those prerequisites are met, we can run the script from the **migrate-state** directory:

    ./migrate_workspaces.sh
    -------
    Migrating state for workspace: shared-network-dev
    -------
    Initializing Terraform with TFC backend and pulling state
    Initializing Terraform Cloud...
    Initializing provider plugins...
    - Finding latest version of hashicorp/azurerm...
    - Installing hashicorp/azurerm v3.90.0...
    - Installed hashicorp/azurerm v3.90.0 (signed by HashiCorp)
    ...
    
    Terraform Cloud has been successfully initialized!
    ...
    
    Pulled Terraform state from TFC
    Initializing Terraform with env0 backend and pushing state
    Initializing the backend...
    
    Successfully configured the backend "remote"! Terraform will automatically
    use this backend unless the backend configuration changes.
    Initializing provider plugins...
    Terraform has been successfully initialized!
    Pushed Terraform state to env0
    

The script will find the **data.json** file generated earlier and use its contents to migrate the state data for each workspace.

Looking at the State tab for the `shared-network-dev` environment, there is now an entry for the data we just copied over.

![env0 State tab](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d2234a48fded0472e56adf_oMZLw4jJB-vo1grK-WYTAlDDBZXIKdMxeHVL0FhU7Dx_No5BCB44uIjd3rX9LK2_nKG04vw-0m6_d5ZbwX84BOu7Qlsu0OOspXbf9AK_Eyzte_3CVjLFp6QqSKJgvtwHLShXquOOnD1z5lg3a1eduuI.png)

Our last step is to confirm the environment is set up and working properly.

### **Test an Environment**

In the `shared-network-dev` environment, we’ll first update the `ARM\_CLIENT\_SECRET` environment variable with the correct value.

![Environment variable in env0](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d2234a2a00d47c33a691e8_BhXRsItGgzt-uc9Vk-EEsch7qhRgtUnMajCH10d2ZZAiktVcKH3IqULu897ukp9EzKuh7zz_E4ONqla_qtv_r4WJ3ljjZslO6kJV6dWZItk5L4bHy0tk4onYyQU2dyBN0l1ZvnroxDNCLFLxCvfeg5k.png)

And then kick off a Redeploy action to verify that the environment matches the actual infrastructure deployed in Azure. After a few minutes, the plan comes back that no changes are required, meaning that the infrastructure matches the configuration.

![Terraform plan in env0](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d2234aa7c957c2dfe04798_N26okFYuD3iM0iYySp3iEqy-QuAESrBa4qYH-u88uoOSEMe88ZIFoCEGs3LHhtdwL_jG2wKYNMX3veNkhZ1EigqgrsDFsyxsaK89ZncZ0eyC0uDSdkjOJ9vwvzrckKz3LSBeA-0iFoFVzDvh_9gJNho.png)

Success!

We have migrated our workspaces from Terraform Cloud to env0 without impacting the actual infrastructure!

### **Key Points to Note for a Successful Migration**

Here are a few considerations and aspects to keep in mind for a smooth experience:

*   You will need to be able to run a bash script for state migration.
*   Workspaces that have a VCS workflow enabled are supported.
*   Variable sets associated with a workspace or project are not exported.
*   Permissions assigned to projects and workspaces are not exported.
*   Modules stored in the private registry are not exported.
*   Policy sets associated with the workspaces are not exported.

**Post-migration setup and features**
-------------------------------------

After completing the migration process, there are just a few tasks we recommend doing: 

*   Verify that your env0 account has access to the VCS repositories used by each workspace
*   Configure permissions on each workspace to match Terraform Cloud
*   Set up cloud provider credentials for each workspace if they were not part of the migrated variables

While you're at it, you can also take advantage of some excellent features of env0:

*   [**Drift Detection**](https://www.env0.com/blog/tutorial-achieving-auto-remediation-with-env0) - Enables you to stay one step ahead of all discrepancies between target environments and source infrastructure code, enabling you also to create  scheduled checks for infrastructure drift and notify your teams when an environment is in a _drifted_ state.
*   [**Cost Monitoring**](https://www.env0.com/blog/finops-meets-iac-granular-cloud-cost-optimization-with-env0) - Continuously tracks your actual cost, using patented technology, augmented by the ability to granularly set budget thresholds and auto-notifications.
*   [**OPA Integration**](https://www.env0.com/blog/opa-tutorial-leveraging-env0-for-advanced-cloud-policy-management) \- Flexible way to configure Policy-as-Code for your environments using the Open Policy Agent. If you're already using OPA on Terraform Cloud, you can use the same policies with env0.

**What else you should know about env0**
----------------------------------------

Since you're already considering a migration to env0, here are a few important things you should know about the platform:

### **It supports ALL the relevant frameworks** 

env0 goes beyond Terraform and OpenTofu, integrating effortlessly with additional tools like CloudFormation, Pulumi, Kubernetes, and Helm. 

This is useful, especially for cloud-native environments that make heavy use of Helm and Kubernetes, being able to use a single platform to manage all of your IaC real estate is a huge time saver and lowers administrative overhead.

### **It's designed to offer maximal flexibility and enhanced reliability** 

env0 uses a hierarchy consisting of five layers, each of which can inherit settings and permissions from the parent scope. The five layers start at the organization, and then down through templates, projects, environments, and workflows.

Each layer can contain variable values to use in the workflow that is executed for an environment. Importantly, policies and permissions can also be applied at each scope, creating a robust management structure scaling well beyond a handful of environments. 

This is especially helpful for organizations looking to expand IaC usage across different teams and promote managed self-service.

### **It streamlines complex environment management** 

Complex infrastructure architectures should be decoupled into separate configurations to simplify deployment and reduce the blast radius of changes. However, expressing dependencies across those configurations and sequencing the workflow can act as a barrier to adopting this practice.

env0 includes a multi-environment, tiered workflow option that allows you to express dependencies and deployment order of sub-environments using a declarative YAML file. And because env0 supports multiple frameworks, you can combine those frameworks in a single workflow to fully express your complex architecture.

### **It accelerates development processes with rapid iteration**

env0’s remote backend supports running remote operations from the command line to test uncommitted changes while still taking advantage of the custom workflows defined for an environment. 

Developers can rapidly iterate through IaC testing and validation using their local environment before formally promoting changes through VCS, improving developer productivity and streamlining the change process.

Even better, you are not required to store state data on env0’s remote backend to take advantage of remote operations. 

Some customers must store state data in their own self-hosted backend, and we’re happy to provide the best of both worlds, flexible state data hosting and remote operations.

**Wrap up**
-----------

Infrastructure engineers should be able to pick the solution that meets their needs today and be able to shift to a different solution if the need arises. env0’s  Terraform Cloud migration tool helps do just that, simplifying and automating the process of migrating your Terraform Cloud workspaces to the platform.

To learn more about this and other env0 features, [schedule a demo](https://www.env0.com/demo-request) with a technical expert to see the platform in action.