Switch from Terraform Cloud in Minutes with Our New Migration Tool

env0team

env0 Team

Posted on March 11, 2024

Switch from Terraform Cloud in Minutes with Our New Migration Tool

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 to env0 simple, quick, and convenient.

Why migrate from Terraform Cloud?

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 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.

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

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. 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 and env0.

env0 migration tool

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

a screen showing TFC workspaces

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

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

workspace variables prefix

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
Enter fullscreen mode Exit fullscreen mode

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-*"]
Enter fullscreen mode Exit fullscreen mode

And set the environment variable TFE_TOKEN to our Terraform Cloud API token:

$ export TFE_TOKEN=lHk3h0yEenY8WA.atlasv1.zgGLxGx0478VFyKkqQHi4MOvYoJ5oNHW8W1i8ba...
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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, we need to configure a couple environment variables to authenticate to env0:

$ export ENV0_API_KEY=yqyox_b8rogfq
$ export ENV0_API_SECRET=bChV5uX1feH9SA4muesySOWRnN2iafJ
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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

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

Variables in env0

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

$ terraform login
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

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

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

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 - 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 - Continuously tracks your actual cost, using patented technology, augmented by the ability to granularly set budget thresholds and auto-notifications.
  • OPA Integration - 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 with a technical expert to see the platform in action. 

💖 💪 🙅 🚩
env0team
env0 Team

Posted on March 11, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related