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

What is Terraform state? 

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.

Types of Terraform state store

There are two types of store for Terraform state: local and remote.

  • Local state refers to Terraform state stored on the local filesystem, i.e. on your laptop or whatever system you are running the [.code]terraform[.code] command from.
  • Remote state is Terraform state stored remotely, such as in an S3 bucket or a database like PostgreSQL.

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

Why do you need Terraform Remote State?

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:

  • No underlying infrastructure setup and management: env0 takes care of the setup as opposed to other approaches, where you need to do all the setup and management yourself (for example, the S3 backend requires you to create an S3 bucket and an optional DynamoDB table for locking beforehand).
  • Security: env0 stores the state securely for you and assures only you can access it.
  • State consistency: Remote backend ensures users won’t overwrite each other's state by using a locking mechanism and that they receive the most recent state on every Terraform operation.
  • Local runs: By providing the remote backend configuration and a successful login, users can run Terraform operations locally while still working on a shared state.

Using env0's Remote Backend has additional advantages:

  • No Terraform backend configuration when running inside env0: You don't have to provide any type of configuration, you just deploy your code as is and env0 will automatically configure it to use the remote backend.
  • States UI: View the current version of your state as well as all the previous versions.
  • Correlation of Deployment to State: Easily figure out which deployment handles a specific change to your state.

The problem that remote state solves for enterprise teams collaborating on IaC

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.

Why not just use Git?

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

How to set up Terraform remote state using env0

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.

Implementing remote backend for remote state using env0

There are a few common patterns we see.

Scenario 1: No Existing Backend

GitHub link: provider.tf 

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]

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "4.24.0"
    }
  }
# scenario 1 no backend defined
}
provider "aws" {
  region = "us-west-2"
}

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.

Scenario 2: Enable Local Execution to env0 Remote Backend

GitHub link: provider.tf 

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:

  1. You have a login token
  2. The current path is the directory of the Terraform stack
  3. The Terraform stack defines a properly configured env0 backend

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.

Backend Configuration

terraform {
  backend "remote" {
    hostname = "backend.api.env0.com"
    organization = "YOUR_ORGANIZATION_ID.YOUR_PROJECT_ID"
‍
    workspaces {
      name = "YOUR_WORKSPACE_NAME"
    }
  }
}

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.

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "4.24.0"
    }
  }
‍
  backend "remote" {
    hostname = "backend.api.env0.com"
    organization = "ebc19c6d-d0dc-3b22-a951-8f43ee49db92"
    
    workspaces {
      name = "static-website-dev1"
    }
  }
}
‍
provider "aws" {
  region = "us-west-2"
}

Scenario 3:  Self-managed S3 as Remote Backend

GitHub link: provider.tf 

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.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "4.24.0"
    }
  }
  # scenario 2 - using "s3" backend
  backend "s3" {
    bucket         = "env0-acme-tfstate"
    dynamodb_table = "env0-acme-tfstate-lock"
    key            = "acme-demo-s3"
    region         = "us-west-2"
    # the role is being assumed from the deployer role - so you will need to configure assume role chaining
    role_arn       = "arn:aws:iam::326535729404:role/env0-acme-assume-role" 
    # external_id    = "value"  # (optional) use ENV0_TERRAFORM_BACKEND_CONFIG=external_id=[external_id_value]
  }
}
provider "aws" {
  region = "us-west-2"
}

Scenario 4: Migrate Existing State to env0’s Remote Backend

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.

Terraform Remote State & Remote Backend Best Practices

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 state file slows development velocity because only one dev can change the state file 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 state file for every apply.

Smaller, microservices-styled, minimum viable state files 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 (RBAC) to meet the needs of security/hovernance/compliance is essential to delivering infrastructure as code value.

Without these concerns addressed, infrastructure deployments become a bottleneck to velocity.

Summary

"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!

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.

To learn more about Terraform, check out this Terraform tutorial.

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

What is Terraform state? 

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.

Types of Terraform state store

There are two types of store for Terraform state: local and remote.

  • Local state refers to Terraform state stored on the local filesystem, i.e. on your laptop or whatever system you are running the [.code]terraform[.code] command from.
  • Remote state is Terraform state stored remotely, such as in an S3 bucket or a database like PostgreSQL.

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

Why do you need Terraform Remote State?

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:

  • No underlying infrastructure setup and management: env0 takes care of the setup as opposed to other approaches, where you need to do all the setup and management yourself (for example, the S3 backend requires you to create an S3 bucket and an optional DynamoDB table for locking beforehand).
  • Security: env0 stores the state securely for you and assures only you can access it.
  • State consistency: Remote backend ensures users won’t overwrite each other's state by using a locking mechanism and that they receive the most recent state on every Terraform operation.
  • Local runs: By providing the remote backend configuration and a successful login, users can run Terraform operations locally while still working on a shared state.

Using env0's Remote Backend has additional advantages:

  • No Terraform backend configuration when running inside env0: You don't have to provide any type of configuration, you just deploy your code as is and env0 will automatically configure it to use the remote backend.
  • States UI: View the current version of your state as well as all the previous versions.
  • Correlation of Deployment to State: Easily figure out which deployment handles a specific change to your state.

The problem that remote state solves for enterprise teams collaborating on IaC

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.

Why not just use Git?

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

How to set up Terraform remote state using env0

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.

Implementing remote backend for remote state using env0

There are a few common patterns we see.

Scenario 1: No Existing Backend

GitHub link: provider.tf 

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]

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "4.24.0"
    }
  }
# scenario 1 no backend defined
}
provider "aws" {
  region = "us-west-2"
}

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.

Scenario 2: Enable Local Execution to env0 Remote Backend

GitHub link: provider.tf 

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:

  1. You have a login token
  2. The current path is the directory of the Terraform stack
  3. The Terraform stack defines a properly configured env0 backend

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.

Backend Configuration

terraform {
  backend "remote" {
    hostname = "backend.api.env0.com"
    organization = "YOUR_ORGANIZATION_ID.YOUR_PROJECT_ID"
‍
    workspaces {
      name = "YOUR_WORKSPACE_NAME"
    }
  }
}

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.

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "4.24.0"
    }
  }
‍
  backend "remote" {
    hostname = "backend.api.env0.com"
    organization = "ebc19c6d-d0dc-3b22-a951-8f43ee49db92"
    
    workspaces {
      name = "static-website-dev1"
    }
  }
}
‍
provider "aws" {
  region = "us-west-2"
}

Scenario 3:  Self-managed S3 as Remote Backend

GitHub link: provider.tf 

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.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "4.24.0"
    }
  }
  # scenario 2 - using "s3" backend
  backend "s3" {
    bucket         = "env0-acme-tfstate"
    dynamodb_table = "env0-acme-tfstate-lock"
    key            = "acme-demo-s3"
    region         = "us-west-2"
    # the role is being assumed from the deployer role - so you will need to configure assume role chaining
    role_arn       = "arn:aws:iam::326535729404:role/env0-acme-assume-role" 
    # external_id    = "value"  # (optional) use ENV0_TERRAFORM_BACKEND_CONFIG=external_id=[external_id_value]
  }
}
provider "aws" {
  region = "us-west-2"
}

Scenario 4: Migrate Existing State to env0’s Remote Backend

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.

Terraform Remote State & Remote Backend Best Practices

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 state file slows development velocity because only one dev can change the state file 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 state file for every apply.

Smaller, microservices-styled, minimum viable state files 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 (RBAC) to meet the needs of security/hovernance/compliance is essential to delivering infrastructure as code value.

Without these concerns addressed, infrastructure deployments become a bottleneck to velocity.

Summary

"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!

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.

To learn more about Terraform, check out this Terraform tutorial.

Logo Podcast
With special guest
Andrew Brown

Schedule a technical demo. See env0 in action.

CTA Illustration