8i | 9i | 10g | 11g | 12c | 13c | 18c | 19c | 21c | 23c | Misc | PL/SQL | SQL | RAC | WebLogic | Linux

Home » Articles » Misc » Here

Terraform : Backends - Manage State Snapshots Remotely

This article gives an overview of how to manage state snapshots remotely in Terraform using backends.

Related articles.

Introduction

By default terraform tracks the state of the build locally. That works fine, but what if we have more than one person working with Terraform? How do those people keep their local state in sync? Defining a backend allows Terraform to save state snapshots in a remote location, so multiple people can have their state information in sync.

There are many services that can be used as a backend, and each of them require a slightly different configuration, but they are all listed in the documentation and they follow the same pattern.

Not all backends are alike though. Some support state locking and some don't. State locking is a mechanism for serializing changes, so two people working on the same area don't accidentally affect each other. If you are working with a backend that doesn't support state locking, you will need a manual process to prevent errors.

In this example we will be using Artifactory as a backend, which doesn't currently support state locking. It assumes we have a generic repository called "my-terraform-state" on Artifactory.

Backend Definition

Backends are configured in Terraform as part of the "terraform" section. You may already have this section with provider specific information, but if you haven't, just add it. The backend must reference one of the supported backends, and supply the parameters required for that backend. Here is an example of using Artifactory.

terraform {
  backend "artifactory" {
    username = "my-artifactory-username"
    password = "my-artifactory-api-key"
    url      = "https://mycompany.jfrog.io/artifactory"
    repo     = "my-terraform-state"
    subpath  = "my-terraform-state"
  }
}

This would work, but we are hard coding the credentials into our terraform, and we don't want credentials to be committed to version control. Instead we will typically put the parameters into a backend config file in our working directory, making sure we don't commit this to version control. We create a file called "config.artifactory.tfbackend" with the following contents.

username = "my-artifactory-username"
password = "my-artifactory-api-key"
url      = "https://mycompany.jfrog.io/artifactory"
repo     = "my-terraform-state"
subpath  = "my-terraform-state"
Terraform doesn't care about the backend config file name, but the documentation recommends a name in the form of "*.backendname.tfbackend".

Now we can define the backend as follows.

terraform {
  backend "artifactory" {}
}

Initialize the Backend

Once the backend definition is in place, we need to initialize the backend, to make sure our current local state is stored in the backend. If we are using a backend config file we need to specify the location.

# Hard coded backend.
terraform init

# Backend config file.
terraform init -backend-config=config.artifactory.tfbackend

This is a one-off action, as the backend configuration is saved in the ".terraform/terraform.tfstate" file. Here's an example of the contents of that file.

{
    "version": 3,
    "serial": 10,
    "lineage": "66a209a2-609b-d6c6-4870-97731efde168",
    "backend": {
        "type": "artifactory",
        "config": {
            "password": "my-artifactory-api-key",
            "repo": "my-terraform-state",
            "subpath": "my-terraform-state",
            "url": "https://mycompany.jfrog.io/artifactory",
            "username": "my-artifactory-username"
        },
        "hash": 1831485929
    },
    "modules": [
        {
            "path": [
                "root"
            ],
            "outputs": {},
            "resources": {},
            "depends_on": []
        }
    ]
}

As part of the initialization, the local "terraform.tfstate" file is backed up to the "terraform.tfstate.backup" file, the current contents saved to the backend, and the "terraform.tfstate" file is emptied.

Once the backend is initialized we can work as normal.

Changing Backends

The backend definition is part of the Terraform state, so if you change it at any point, Terraform will know. To remove the current backend, simply remove the backend definition and issue the terraform init command. Terraform will copy the state back from the previous backend to the local "terraform.tfstate" file.

You can change between backends in the same way. Define your new backend and issue the terraform init command using the -backend-config flag, which will copy the current state from the old backend to the new backend.

For more information see:

Hope this helps. Regards Tim...

Back to the Top.