Documentation · Infrastructure runs
Moving state from HCP Terraform
Migrating existing state with terraform init -migrate-state, from a cloud block, the remote backend, or another backend entirely.
Your existing state moves with terraform init -migrate-state. The CLI does the copying; what you change is the hostname.
Before you start, have a token (see API tokens) and your organisation name, which is the account on the Terraform card on Settings in the dashboard, and put the token in the environment:
export TF_TOKEN_tf_runners_io=<your token>There is no terraform login step. That flow needs a browser round trip on a path tf.runners.io does not serve, so tokens come from the dashboard instead — see API tokens.
Terraform will not migrate state while a cloud block is in force, so the route is cloud → remote → migrate → cloud again.
Your configuration looks something like this:
hclterraform { cloud { hostname = "app.terraform.io" organization = "your-organization" workspaces { name = "my-workspace" } } }Change it to use
remote, temporarily, leaving the hostname alone:hclterraform { backend "remote" { hostname = "app.terraform.io" organization = "your-organization" workspaces { name = "my-workspace" } } }Remove the initialised backend so the next
initre-resolves it:bashrm -r .terraformContinue with If you use the
remotebackend below.
Change the hostname, and the organisation if the name differs here:
hclterraform { backend "remote" { hostname = "tf.runners.io" organization = "your-organization" workspaces { name = "my-workspace" } } }Migrate:
bashterraform init -migrate-stateTerraform notices the backend configuration has changed and offers to copy the existing state. Answer
yes.Initializing the backend... Backend configuration changed! Do you want to copy existing state to the new backend? Pre-existing state was found while migrating the previous "remote" backend to the newly configured "remote" backend. No existing state was found in the newly configured "remote" backend. Do you want to copy this state to the new "remote" backend? Enter a value: yesOptionally move back to a
cloudblock, which is what you want if you use workspace tags:hclterraform { cloud { hostname = "tf.runners.io" organization = "your-organization" workspaces { name = "my-workspace" } } }bashterraform initAnswer
yesagain. Despite what the output says about copying state, nothing is copied at this step — your state arrived in the previous one. This prompt is the CLI switching which backend it talks to.
Coming from s3, gcs, azurerm, local or similar, replace the backend block with a cloud block and reinitialise:
terraform {
cloud {
hostname = "tf.runners.io"
organization = "your-organization"
workspaces {
name = "my-workspace"
}
}
}terraform initAnswer yes when asked whether to migrate the existing state.
Mostly nothing, and the exceptions are worth knowing before rather than after.
Runs execute OpenTofu. Your configuration is unchanged; the binary running it is not the one HCP uses. Why.
There are no projects. Workspaces belong to the organisation directly. If you use dynamic credentials, the token subject loses its
project:segment and your cloud's trust policy needs the same edit — see dynamic credentials.Inviting people is done on the dashboard, not through the
organization-membershipsAPI, which answers501here on purpose. Adding an existing user to a team over the API works normally. See the Terraform API.emailandmicrosoft-teamsnotifications are not supported.generic,slackandgcppubsubare. See notifications.No policy-as-code, and drift detection is not available yet. If either is load-bearing for you, that is the thing to weigh before moving.
Move one workspace first, ideally one whose state you could rebuild. Confirm a plan comes back with no unexpected diff — an empty plan against migrated state is the check that the migration worked, and it takes a minute.
Your old state is not deleted by any of this. HCP still holds it until you remove it, which makes the whole of the above reversible right up to the point you tidy up.