By default, Terraform stores state locally as [.code]terraform.tfstate[.code]. While this works for personal projects, it becomes a bottleneck to collaboration on Infrastructure as Code (IaC) when working in a team. This is because team members need to have the latest state before deploying, and a way to manage who applies their Terraform first. Otherwise, developers end up stepping on each other's toes and overwriting important changes. The solution is to use a remote backend, where Terraform writes the state to a shared store, accessible to the team members.
There are many ways to set up remote state, but in this guide we will focus on configuring a Terraform backend with env0. This is a good option because env0 provides a way to manage the infrastructure code using its interface, and it integrates well with Terraform. And as of our latest release, env0 can now store your state remotely. Our managed remote backend magically works—no underlying infrastructure required. All you have to do is check a checkbox!
“Instead of going through the trouble of creating and maintaining a remote backend — including the backup, replication, high availability, encryption, and locking — you can now use env0 to manage your state file in the same place where you run and deploy your Infrastructure” - Omry Hay, CTO @ env0
Terraform state is the mapping of your desired configuration to deployed resources. It answers the question, “What did I say should be deployed?” and how that differs from “What is actually deployed?”
By default, Terraform stores your state in a [.code]terraform.tfstate[.code] on the local machine.
This [.code]terraform.tfstate[.code] file allows Terraform to detect discrepancies between your configuration and deployed resources. For example, if a change was made to your provisioned resources through a GUI but was not defined in the infrastructure code, Terraform knows the difference because of the state file.
There are two types of store for Terraform state: local and remote.
A remote backend is remote state that can be shared, providing helpful capabilities such as preventing conflicts and inconsistencies.
"Even if you're working alone, let's say you're the only one managing infrastructure, you should still think about backups and to have the state secured, and to have redundancy." - Hila Fish, Sr DevOps Engineer @ Wix
Using remote state is a best practice in an Enterprise, or when collaborating across a team. The main reason for using remote state is to have a single source of truth. This protects against divergent state files, or multiple copies of state files. When working on IaC as a team, having state stored remotely ensures consistency, so that any developer will know what changes have already been applied and not inadvertently overwrite or revert another's changes. Remote state helps to avoid merge conflicts.
Terraform offers several state storage options, of which env0 supports remote backend, which has some significant benefits such as:
Using env0's Remote Backend has additional advantages:
Here's a practical example we've seen across Terraform users. Let’s say you're part of a DevOps/Platform team, providing standardized templates to be consumed by other business units. David the Developer writes a Terraform module for an S3 bucket that hosts a static website and deploys to the cloud, but mistakenly gives it a private ACL so it's not accessible. Saul the Engineer catches this mistake, changes the ACL to be public-read, and runs [.code]terraform apply[.code]. Later that day, David the Developer edits the code to enable logging, and runs [.code]terraform apply[.code] again. But because the state file is stored locally on each of their respective machines, David's [.code]terraform apply[.code] doesn't have the "public-read" ACL change, and the site becomes inaccessible once again.
Instead, when we have configured remote state, Terraform reads the state from the server and ensures that it's working with the most up-to-date information.
Now, you might interject here, and propose committing your Terraform state to a Git repository. While this is certainly a solution that works, it's not advisable to commit state to a Git repo because state contains sensitive data, such as passwords, API keys, and other secrets. There is a great security risk to putting that type of information in a Git repo (plus, it also won’t really work, as people can either change the state and not commit it, or have old versions since they did not pull before running applies.)
Furthermore, committing state to Git requires human intervention. What if either David the Developer or Saul the Engineer forget to commit their [.code]tfstate[.code]? We end up in the same dilemma as before—with team members making unwanted changes.
"Not using remote state and a remote backend for your terraform is like riding a bike with training wheels on. You might technically be on a bike... but you're not really doing it properly." Matt Gowie, Masterpoint
Remote state has traditionally been enabled using a cloud specific backend (e.g. S3 in AWS, Azure Blob Storage, or Google Cloud Storage). With this new release, env0 provides a way to manage Terraform state securely and efficiently, without the need to provision and maintain a cloud backend. Here's how to set up remote backend and take advantage of remote state easily by using env0.
There are a few common patterns we see.
In this scenario, you do not have an existing remote state, and do not specify a remote backend configured in your [.code]provider.tf[.code]
To store your remote state in env0, simply check the “Use env0 Remote Backend” and specify a Workspace Name unique to the Organization.
Our managed remote backend "magically" works - no need to set up any underlying infrastructure or manage state. Literally the only thing for you to do is check the checkbox. No more configuring the backend nor login.
Here we will configure your [.code]provider.tf[.code] to execute using env0’s remote backend. You would still run [.code]terraform plan[.code] and [.code]apply[.code] on your local machine, but the state will be stored in env0.
Local execution allows running your Terraform deployments both on env0 and locally with access to the remote state. To use the remote backend locally, you must login for your requests to be authorized.
To login, ensure the following conditions are met:
Creating a Token
To generate a token, you must create an API key.
Creating API keys can only be done by an Organization Admin. If you do not have this permission, contact an Organization Admin to generate the token.
Logging in is simple. All you have to do is:
[.code]terraform login backend.api.env0.com[.code]
Enter yes when prompted
Insert your token
You may now run your Terraform commands locally as per usual.
Many dev teams are already currently storing state in a resource they control such as an S3 bucket. To utilize an already existing self-managed backend, ensure that your terraform configuration contains the backend block.
We have documentation here detailing the simple steps to do state migration.
We also have a script to help migrate workspaces to env0, including those using remote state. Note that this script is intended for workspaces that have remote backend configured in code. We're working to update it further work to enable state migration from TFC to env0.
Use remote state, not local states
Local state files are okay for small, less-than two-pizza teams. Teams that size have no problem having short toes and keeping track of who’s working on what. But as team size and number of contributors increases, local state becomes a bottleneck that ultimately creates rework and dependencies. Using a remote state ensures you have a single source of truth for your Terraform deployments.
Locking the State File
Lock the state file so developers do not overwrite each other’s changes or corrupt the state.
Plan Locally, Apply Remotely
For faster development cycles, run terraform plan locally, while running terraform apply remotely for a consistent and structured deployment process.
Minimum Viable Remote State (MVRS)
Keep your state files small. Having a monolithic statefile slows development velocity because only one dev can change the statefile at a time. It also tightly couples your infrastructure, which makes your configurations prone to errors that are difficult to debug. Large state files create dependencies that are difficult to keep track of. It also makes build times take longer, because terraform has to parse the entire statefile for every apply. Smaller, microservices-styled, minimum viable statefiles enable developers to work independently of each other and troubleshoot errors faster. Remember the DevOps Ideal of “Locality and Simplicity” (not locality as in local state, lol)
Use a dedicated infrastructure-as-code platform
As infrastructure-as-code usage scales and grows within your team, it’s important to standardize how IaC is written, deployed, and modified. And when your team begins to deploy production infrastructure, there needs to be developer friendly guardrails that protect users from accidentally destroying resources in production. Having standardized tooling that allows Developers to collaborate efficiently on Terraform, provides visibility for DevOps admins into what’s being deployed, and delivers logging, audit trails, and granular Role Based Access Controls to meet the needs of Security/Governance/Compliance is essential to delivering infrastructure as code value. Without these concerns addressed, infrastructure deployments become a bottleneck to velocity.
"Manually managing Terraform remote state has the same hazards as self-hosting your own primary database. You can sure do it, but you sure will regret it when things goes sideways.Managed Terraform Automation platforms all have generous free tiers, and affordable pricing based on the size of organization, why would you want to risk the labour and hazards of manually configuring your own remote state to save a few pennies?" - Andrew Brown, Exampro
With this latest release, env0 can now store your state remotely, and there is no need to set up any underlying infrastructure. Literally the only thing for you to do is check a checkbox!