Hello to all you Terraform Cloud users out there! We have an entire section of our website dedicated to the key features and platform differences between env0 and Terraform Cloud that make us the best Terraform Cloud Alternative. More and more customers have been migrating from Terraform Cloud to env0, and we have been asked quite a few times what the POC / Migration process looks like. The typical engineering answer is “it depends.” The good news there is that we can help answer some of the questions you may have that would help you make the right migration decisions. This blog is going to dive into the decisions that need to be made, env0’s recommendations, and then we’ll get to the meat of the process. So let’s jump right in!

Questions to Answer

As with any kind of project or design, there are a bunch of questions we need to answer first. For the task of migrating a user who is all-in on Terraform Cloud to env0, these are the questions we need answers to:

What are we going to migrate? Remote Runs? State? Both?

The main feature that customers are looking to migrate is obviously going to be the remote runs. The main function of env0 and Terraform Cloud is to consolidate and manage the Terraform runs so that you don’t have to do it all from each user’s laptop. If you’re not looking to migrate remote runs, then this blog doesn’t really apply to you, as there really isn’t any advantage to that. The real question is going to be what you’re going to do with the state.

How are you going to manage the state? S3 / Cloud Storage? env0? Terraform Cloud?

As we just mentioned, migrating applies is pretty much a given at this point. But what about the state? There are so many options. But it comes down to what you’re doing with it now. If you are doing your Terraform runs on Terraform Cloud, are you using the same platform for the state? Or are you using a solution like an S3 remote backend in your own cloud? Our recommendation for the migration procedure depends on what your answer to this question is.

env0 Recommendation

Now that we’ve gotten some of the questions out of the way, let’s talk about env0’s recommendations. We talked about how if you’re not moving applies, there’s really nothing to do. env0 does not offer remote state backend capabilities…yet (Stay tuned). We will manage your state for you if you do not have a backend configuration in the code, but it is always best practice to manage your own state in your own cloud account, due to the sensitive nature of the contents of the state file. Because of this, our first recommendation is to move your Terraform remote runs to env0. This way you can take full advantage of the env0 platform.

Second, it is a general recommendation for any Terraform user to use a backend other than Local. There is a large amount of sensitive data inside the state, so securing it inside of your own cloud environment is always best. Terraform Cloud will store state for you, as will env0 if you do not specify a backend in the code. Therefore, we recommend you set up an s3 bucket or other cloud storage bucket in your cloud account to use. You can find documentation on backend configuration here. You can find specific information on using S3 here. If you still want to use Terraform Cloud as the remote backend, or if you just want to evaluate env0 without changing the Terraform Cloud backend, you can do so by following the instructions here.

Migration Procedure

Setup: I have a deployment running in my Terraform Cloud workspace. I am using the two-tier application example from the AWS Terraform Provider repository. You can see the code here.

And a quick look at my variable setup for this specific Workspace:

Also good to note that we want to disable the continuous deployment trigger at this point. We don’t want Terraform Cloud pushing deployments any longer. You can set the Apply to manual. This is in the Settings -> General -> Manual Apply

Alright, we are done with all the boring paperwork and pre-work. We’ve finally made it to the fun part. Let’s talk about the actual migration process. We’re going to assume for this guide that you are currently using Terraform Cloud for Applies and for State and that you want to migrate fully off Terraform Cloud. This is going to require some local (or jump-server) CLI work, as Terraform Cloud doesn’t support the ability to migrate the state off TFC to another provider. It’s pretty straightforward, so let’s take a look at the overall process:

  • Install / Configure Terraform Locally
  • Git Clone the repository to the machine
  • Run [.code]terraform init[.code] against the current state configuration
  • Change the Backend configuration in the code
  • Run [.code]terraform init[.code] again to migrate the state
  • Git Commit / Push to update the backend config change into the repo
  • Create Project & Template in env0
  • Deploy the environment in env0 specifying the Workspace name
  • Delete the workspace from Terraform Cloud without destroying the deployment.

So let’s do it!

Install / Configure Terraform Locally

This one is pretty straightforward. Because of the inability to migrate state away from TFC to something else from the TFC interface, we just need to snag the files and do this locally. You can do this on your local machine, or from a jump server if you prefer. Just some machine you can run the terraform CLI on, and that you can Git Clone files on to execute against. To install Terraform CLI you can find the method here. (Just make sure you download the same version as you’re currently using.)

You’ll need to log in to Terraform Cloud with the CLI so that you can use your remote backend on TFC from your local machine. If it can’t login to TFC< it can’t grab the state to migrate it. Running the following command will prompt you to get an API token that you can use

[.code]terraform login[.code]/

When you’re done, it should look like this:

Git Clone the repository to the machine

You will need a copy of the files locally so that we can do the Terraform Init to migrate the backend to our Cloud provider. So do a Git Clone of your repository onto the machine you’ll be doing the work on.

Run [.code]terraform init[.code] against the current state configuration

The local copy and terraform CLI need to know that there is already a copy of the deployment out there running. So we’ll just run a quick command against the files

terraform init

You should see an update in the TFC UI for your state update. This is a sign that the init / connection is successful.

Change the backend configuration

For this, I am just going to jump into VI and change the ‘terraform’ code block so that it now points at my desired S3 backend. Your bucket name and all will be different, just set it to what you need it to be. Because env0 will need to Read / Write to this later, just set the “key” to [.code]terraform.tfstate[.code] like so:

terraform {
backend “s3” {
encrypt = true
bucket = “bucket-tfstate-td”
key = “terraform.tfstate”
region = “us-east-1”
}
}

Run [.code]terraform init[.code] again to migrate the state

This one is a bit different than the last one. Because we’re going to be migrating the state, we need to add that flag to the command [.code]terraform init -migrate-state[.code].

You’ll be asked to confirm the state migration by typing ‘yes’ and hitting enter.

Then it’s done!

We can see from the above that the state was migrated. And we can validate that in S3:

Now we’re in a position where our Applies are hosted on TFC still, but our backend has been migrated to a 3rd-party location so that we can now shift the applies over to env0. Let’s do some quick clean-up, and get to env0!

Push to update into the repo (Git Commit)

Because we made changes to the terraform files locally so that we could migrate the backend, we need to get that code back to our repository so that when we try to execute it in env0, the new backend information is used as opposed to the old TFC backend. You can do this with a Git Commit and Git Push right from where you were, or you can use whatever method you’d like. to get that updated in the repo. We’ve validated that update in GitHub here:

Now let’s jump into env0 and get this migration finished up!

Create the Project & Template in env0

We have created a project inside the env0 platform called Terraform Cloud Migration Demo:

Inside this project, we have configured the AWS Cloud credentials so we can use AWS Assumed Role. This is a feature that is not available in Terraform Cloud. Check our out docs on how to do that here. Not using AWS, or just want to use regular key + secret? No problem! env0 can deploy to any cloud that there is an Infrastructure as Code provider for. Docs on cloud account credential configuration are here.

For our template, we’ll put some basic details on it. It is important to note that unlike setting up a Workspace in TFC when you set up a template in env0, you can use that template for multiple different projects and environments. Workspaces in TFC can’t be cloned.

We’ll link our template to our repository, set our default branch, and point the template at our Terraform Folder. This structure allows us to support mono-repo and multi-repo strategies.

env0 has the ability to scope variables at the Org (global), Project, Environment, and even template level. So you don’t have to keep copy/pasting variables when they will be re-used across templates or projects. But, unfortunately, we’ll need to go fetch those variables somehow out of the existing Terraform Cloud Workspace, and set them up in env0. You can rest assured your secrets are safe with us. We have our SOC 2 Type II report available for the SaaS platform, and even a Self-Hosted Agent available for next-level security and control. Read more about our security here.

Deploy the environment in env0 specifying the Workspace name

We are set to go for our first “deployment.” Don’t worry, though. This is not going to mess up what you already have. We actually recommend doing it the first time without Cloud Credentials, if you want to be extra cautious. This will let you validate the Terraform Init step for variables, etc. Because we have the state in place already, and we’re specifying a workspace name in env0. Because we migrated the state from TFC to S3, the Terraform CLI set the workspace name as ‘default’ for the migrated state. So we’ll do our deployment with the template we created and set the Workspace Name to default. Also make sure your Destroy Environment (TTL) is set to Unlimited. And be very careful about un-checking the Approve Plan Automatically button, as we want to validate the plan before any applies are done.

Because there were no changes to any of the objects in the state, env0 is going to read the state and see that we don’t have anything to do. So we’ll just hit Approve and finish up.

One step to point out here is the Tag Resources step. When you enable Cost Monitoring on your project, this is where our open-source project Terratag runs so that your resources are tagged so that we can collect the actual cost data for the deployment.

And then we just have to check the plan out and validate it is going to work properly.

Done!

And our S3 bucket state file was updated! Confirmed with the time stamp.

Delete the workspace from TFC without destroying the deployment.

Last, but not least, we need to clean up TFC. We’ll go into the Workspace and click on Settings -> Destruction & Deletion

We want to make sure we Delete Workspace. If you select Destroy, it will possibly reach out and nuke your cloud resources. We wanted to do this live, so select Delete. Type the workspace name, and it’s gone!

That’s it! Your life workloads from Terraform Cloud are still running and inherited into env0 for future management. In order to test that everything is working properly, you can make a comment update or something similar to one of your Terraform files, opening a Pull Request, and validating that the Pull Request Plan runs and generates inside your SCM.

To learn more about the advantages of migrating from Terraform Cloud to env0, check out our Terraform Cloud Alternative page.

Hello to all you Terraform Cloud users out there! We have an entire section of our website dedicated to the key features and platform differences between env0 and Terraform Cloud that make us the best Terraform Cloud Alternative. More and more customers have been migrating from Terraform Cloud to env0, and we have been asked quite a few times what the POC / Migration process looks like. The typical engineering answer is “it depends.” The good news there is that we can help answer some of the questions you may have that would help you make the right migration decisions. This blog is going to dive into the decisions that need to be made, env0’s recommendations, and then we’ll get to the meat of the process. So let’s jump right in!

Questions to Answer

As with any kind of project or design, there are a bunch of questions we need to answer first. For the task of migrating a user who is all-in on Terraform Cloud to env0, these are the questions we need answers to:

What are we going to migrate? Remote Runs? State? Both?

The main feature that customers are looking to migrate is obviously going to be the remote runs. The main function of env0 and Terraform Cloud is to consolidate and manage the Terraform runs so that you don’t have to do it all from each user’s laptop. If you’re not looking to migrate remote runs, then this blog doesn’t really apply to you, as there really isn’t any advantage to that. The real question is going to be what you’re going to do with the state.

How are you going to manage the state? S3 / Cloud Storage? env0? Terraform Cloud?

As we just mentioned, migrating applies is pretty much a given at this point. But what about the state? There are so many options. But it comes down to what you’re doing with it now. If you are doing your Terraform runs on Terraform Cloud, are you using the same platform for the state? Or are you using a solution like an S3 remote backend in your own cloud? Our recommendation for the migration procedure depends on what your answer to this question is.

env0 Recommendation

Now that we’ve gotten some of the questions out of the way, let’s talk about env0’s recommendations. We talked about how if you’re not moving applies, there’s really nothing to do. env0 does not offer remote state backend capabilities…yet (Stay tuned). We will manage your state for you if you do not have a backend configuration in the code, but it is always best practice to manage your own state in your own cloud account, due to the sensitive nature of the contents of the state file. Because of this, our first recommendation is to move your Terraform remote runs to env0. This way you can take full advantage of the env0 platform.

Second, it is a general recommendation for any Terraform user to use a backend other than Local. There is a large amount of sensitive data inside the state, so securing it inside of your own cloud environment is always best. Terraform Cloud will store state for you, as will env0 if you do not specify a backend in the code. Therefore, we recommend you set up an s3 bucket or other cloud storage bucket in your cloud account to use. You can find documentation on backend configuration here. You can find specific information on using S3 here. If you still want to use Terraform Cloud as the remote backend, or if you just want to evaluate env0 without changing the Terraform Cloud backend, you can do so by following the instructions here.

Migration Procedure

Setup: I have a deployment running in my Terraform Cloud workspace. I am using the two-tier application example from the AWS Terraform Provider repository. You can see the code here.

And a quick look at my variable setup for this specific Workspace:

Also good to note that we want to disable the continuous deployment trigger at this point. We don’t want Terraform Cloud pushing deployments any longer. You can set the Apply to manual. This is in the Settings -> General -> Manual Apply

Alright, we are done with all the boring paperwork and pre-work. We’ve finally made it to the fun part. Let’s talk about the actual migration process. We’re going to assume for this guide that you are currently using Terraform Cloud for Applies and for State and that you want to migrate fully off Terraform Cloud. This is going to require some local (or jump-server) CLI work, as Terraform Cloud doesn’t support the ability to migrate the state off TFC to another provider. It’s pretty straightforward, so let’s take a look at the overall process:

  • Install / Configure Terraform Locally
  • Git Clone the repository to the machine
  • Run [.code]terraform init[.code] against the current state configuration
  • Change the Backend configuration in the code
  • Run [.code]terraform init[.code] again to migrate the state
  • Git Commit / Push to update the backend config change into the repo
  • Create Project & Template in env0
  • Deploy the environment in env0 specifying the Workspace name
  • Delete the workspace from Terraform Cloud without destroying the deployment.

So let’s do it!

Install / Configure Terraform Locally

This one is pretty straightforward. Because of the inability to migrate state away from TFC to something else from the TFC interface, we just need to snag the files and do this locally. You can do this on your local machine, or from a jump server if you prefer. Just some machine you can run the terraform CLI on, and that you can Git Clone files on to execute against. To install Terraform CLI you can find the method here. (Just make sure you download the same version as you’re currently using.)

You’ll need to log in to Terraform Cloud with the CLI so that you can use your remote backend on TFC from your local machine. If it can’t login to TFC< it can’t grab the state to migrate it. Running the following command will prompt you to get an API token that you can use

[.code]terraform login[.code]/

When you’re done, it should look like this:

Git Clone the repository to the machine

You will need a copy of the files locally so that we can do the Terraform Init to migrate the backend to our Cloud provider. So do a Git Clone of your repository onto the machine you’ll be doing the work on.

Run [.code]terraform init[.code] against the current state configuration

The local copy and terraform CLI need to know that there is already a copy of the deployment out there running. So we’ll just run a quick command against the files

terraform init

You should see an update in the TFC UI for your state update. This is a sign that the init / connection is successful.

Change the backend configuration

For this, I am just going to jump into VI and change the ‘terraform’ code block so that it now points at my desired S3 backend. Your bucket name and all will be different, just set it to what you need it to be. Because env0 will need to Read / Write to this later, just set the “key” to [.code]terraform.tfstate[.code] like so:

terraform {
backend “s3” {
encrypt = true
bucket = “bucket-tfstate-td”
key = “terraform.tfstate”
region = “us-east-1”
}
}

Run [.code]terraform init[.code] again to migrate the state

This one is a bit different than the last one. Because we’re going to be migrating the state, we need to add that flag to the command [.code]terraform init -migrate-state[.code].

You’ll be asked to confirm the state migration by typing ‘yes’ and hitting enter.

Then it’s done!

We can see from the above that the state was migrated. And we can validate that in S3:

Now we’re in a position where our Applies are hosted on TFC still, but our backend has been migrated to a 3rd-party location so that we can now shift the applies over to env0. Let’s do some quick clean-up, and get to env0!

Push to update into the repo (Git Commit)

Because we made changes to the terraform files locally so that we could migrate the backend, we need to get that code back to our repository so that when we try to execute it in env0, the new backend information is used as opposed to the old TFC backend. You can do this with a Git Commit and Git Push right from where you were, or you can use whatever method you’d like. to get that updated in the repo. We’ve validated that update in GitHub here:

Now let’s jump into env0 and get this migration finished up!

Create the Project & Template in env0

We have created a project inside the env0 platform called Terraform Cloud Migration Demo:

Inside this project, we have configured the AWS Cloud credentials so we can use AWS Assumed Role. This is a feature that is not available in Terraform Cloud. Check our out docs on how to do that here. Not using AWS, or just want to use regular key + secret? No problem! env0 can deploy to any cloud that there is an Infrastructure as Code provider for. Docs on cloud account credential configuration are here.

For our template, we’ll put some basic details on it. It is important to note that unlike setting up a Workspace in TFC when you set up a template in env0, you can use that template for multiple different projects and environments. Workspaces in TFC can’t be cloned.

We’ll link our template to our repository, set our default branch, and point the template at our Terraform Folder. This structure allows us to support mono-repo and multi-repo strategies.

env0 has the ability to scope variables at the Org (global), Project, Environment, and even template level. So you don’t have to keep copy/pasting variables when they will be re-used across templates or projects. But, unfortunately, we’ll need to go fetch those variables somehow out of the existing Terraform Cloud Workspace, and set them up in env0. You can rest assured your secrets are safe with us. We have our SOC 2 Type II report available for the SaaS platform, and even a Self-Hosted Agent available for next-level security and control. Read more about our security here.

Deploy the environment in env0 specifying the Workspace name

We are set to go for our first “deployment.” Don’t worry, though. This is not going to mess up what you already have. We actually recommend doing it the first time without Cloud Credentials, if you want to be extra cautious. This will let you validate the Terraform Init step for variables, etc. Because we have the state in place already, and we’re specifying a workspace name in env0. Because we migrated the state from TFC to S3, the Terraform CLI set the workspace name as ‘default’ for the migrated state. So we’ll do our deployment with the template we created and set the Workspace Name to default. Also make sure your Destroy Environment (TTL) is set to Unlimited. And be very careful about un-checking the Approve Plan Automatically button, as we want to validate the plan before any applies are done.

Because there were no changes to any of the objects in the state, env0 is going to read the state and see that we don’t have anything to do. So we’ll just hit Approve and finish up.

One step to point out here is the Tag Resources step. When you enable Cost Monitoring on your project, this is where our open-source project Terratag runs so that your resources are tagged so that we can collect the actual cost data for the deployment.

And then we just have to check the plan out and validate it is going to work properly.

Done!

And our S3 bucket state file was updated! Confirmed with the time stamp.

Delete the workspace from TFC without destroying the deployment.

Last, but not least, we need to clean up TFC. We’ll go into the Workspace and click on Settings -> Destruction & Deletion

We want to make sure we Delete Workspace. If you select Destroy, it will possibly reach out and nuke your cloud resources. We wanted to do this live, so select Delete. Type the workspace name, and it’s gone!

That’s it! Your life workloads from Terraform Cloud are still running and inherited into env0 for future management. In order to test that everything is working properly, you can make a comment update or something similar to one of your Terraform files, opening a Pull Request, and validating that the Pull Request Plan runs and generates inside your SCM.

To learn more about the advantages of migrating from Terraform Cloud to env0, check out our Terraform Cloud Alternative page.

Logo Podcast
With special guest
Andrew Brown

Schedule a technical demo. See env0 in action.

Footer Illustration