Store Terraform state in a Cloud Storage bucket

In this tutorial, you learn how to store Terraform state in a Cloud Storagebucket.

By default, Terraform storesstatelocally in a file namedterraform.tfstate. This default configuration canmake Terraform usage difficult for teams when multiple users run Terraform atthe same time and each machine has its own understanding of the currentinfrastructure.

To help you avoid such issues, this page shows you how to configure aremote state that points to aCloud Storage bucket. Remote state is a feature ofTerraform backends.

Objectives

This tutorial shows you how to do the following:

  • Use Terraform to provision a Cloud Storage bucket to storeTerraform state.
  • Add templating in the Terraform configuration file to migrate the state fromthe local backend to the Cloud Storage bucket.

Costs

In this document, you use the following billable components of Google Cloud:

To generate a cost estimate based on your projected usage, use thepricing calculator.

New Google Cloud users might be eligible for afree trial.

When you finish the tasks that are described in this document, you can avoid continued billing by deleting the resources that you created. For more information, seeClean up.

Cloud Storage incurs costs for storage, read and write operations,network egress, and replication.

The Cloud Storage bucket in this tutorial hasObjectVersioning enabled to keep the history of yourdeployments. Enabling Object Versioning increases storage costs, which you canmitigate by configuringObject Lifecycle Managementto delete old state versions.

Before you begin

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    Cloud Shell is preinstalled with Terraform.

  2. If you're using a local shell, perform the following steps:

  3. Create or select a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.create permission.Learn how to grant roles.
    Note: If you don't plan to keep the resources that you create in this procedure, create a project instead of selecting an existing project. After you finish these steps, you can delete the project, removing all resources associated with the project.
    • Create a Google Cloud project:

      gcloud projects createPROJECT_ID

      ReplacePROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set projectPROJECT_ID

      ReplacePROJECT_ID with your Google Cloud project name.

  4. Verify that billing is enabled for your Google Cloud project.

  5. Enable the Cloud Storage API:

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enable permission.Learn how to grant roles.

    gcloudservicesenablestorage.googleapis.com
  6. Grant roles to your user account. Run the following command once for each of the following IAM roles:roles/storage.admin

    gcloudprojectsadd-iam-policy-bindingPROJECT_ID--member="user:USER_IDENTIFIER"--role=ROLE

    Replace the following:

    Alternately, you can create acustom IAM role that containsthe following permissions:

    • storage.buckets.create
    • storage.buckets.list
    • storage.objects.get
    • storage.objects.create
    • storage.objects.delete
    • storage.objects.update

    As a best practice, we recommend that access to the bucket and the statefiles stored there is controlled. Only a small set of users (for example,the main cloud administrator and the person acting as the alternative orbackup administrator) should have admin permissions for the bucket. Theother developers should have permissions to only write and read objects inthe bucket.

Prepare the environment

  1. Clone the GitHub repository containing Terraform samples:

    gitclonehttps://github.com/terraform-google-modules/terraform-docs-samples.git--single-branch
  2. Change to the working directory:

    cdterraform-docs-samples/storage/remote_terraform_backend_template

Review the Terraform files

  1. Review themain.tf file:

    catmain.tf

    The output is similar to the following

    resource "random_id" "default" {  byte_length = 8}resource "google_storage_bucket" "default" {  name     = "${random_id.default.hex}-terraform-remote-backend"  location = "US"  force_destroy               = false  public_access_prevention    = "enforced"  uniform_bucket_level_access = true  versioning {    enabled = true  }}resource "local_file" "default" {  file_permission = "0644"  filename        = "${path.module}/backend.tf"  # You can store the template in a file and use the templatefile function for  # more modularity, if you prefer, instead of storing the template inline as  # we do here.  content = <<-EOT  terraform {    backend "gcs" {      bucket = "${google_storage_bucket.default.name}"    }  }  EOT}

    This file describes the following resources:

    • random_id: This is appended to the Cloud Storage bucket name toensure a unique name for the Cloud Storage bucket.
    • google_storage_bucket: The Cloud Storage bucket to storethe state file. This bucket is configured to have the followingproperties:
      • force_destroy is set tofalse to ensure that the bucket is notdeleted if there are objects in it. This ensures that the stateinformation in the bucket isn't accidentally deleted.
      • public_access_prevention is set toenforced to make sure thebucket contents aren't accidentally exposed to the public.
      • uniform_bucket_level_access is set totrue to allow controllingaccess to the bucket and its contents usingIAM permissions instead of access control lists.
      • versioning is enabled to ensure that earlier versions of the stateare preserved in the bucket.
    • local_file: A local file. The contents of this file instructs Terraformto use Cloud Storage bucket as the remote backend once thebucket is created.

Provision the Cloud Storage bucket

  1. Initialize Terraform:

    terraforminit

    When you runterraform init for the first time, the Cloud Storagebucket that you specified in themain.tf file doesn't exist yet, soTerraform initializes a local backend to store state in the localfile system.

  2. Apply the configuration to provision resources described in themain.tffile:

    terraformapply

    When prompted, enteryes.

    When you runterraform apply for the first time, Terraform provisions theCloud Storage bucket for storing the state. It also creates a localfile; the contents of this file instruct Terraform to use theCloud Storage bucket as the remote backend to store state.

Migrate state to Cloud Storage bucket

  1. Migrate Terraform state to the remote Cloud Storage backend:

    terraforminit-migrate-state

    Terraform detects that you already have a state file locally and prompts youto migrate the state to the new Cloud Storage bucket. When prompted,enteryes.

After running this command, your Terraform state is stored in theCloud Storage bucket. Terraform pulls the latest state from this bucketbefore running a command, and pushes the latest state to the bucket afterrunning a command.

Clean up

To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, either delete the project that contains the resources, or keep the project and delete the individual resources.

Delete the project

To avoid incurring charges to your Google Cloud account for the resourcesused on this page, follow these steps.

  1. Open themain.tf file.

  2. In thegoogle_storage_bucket.default resource, update the value offorce_destroy totrue.

  3. Apply the updated configuration:

    terraformapply

    When prompted, enteryes.

  4. Delete the state file:

    rmbackend.tf
  5. Reconfigure the backend to be local:

    terraforminit-migrate-state

    When prompted, enteryes.

  6. Run the following command to delete the Terraform resources:

    terraformdestroy

    When prompted, enteryes.

What's next

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.