Local Execution (State-Only Workspaces)
Firefly can act as the remote state backend for your Terraform projects. You point Terraform at Firefly with a standard cloud {} block, and Firefly stores your state, tracks every version, and manages state locking — while your terraform plan and terraform apply continue to run locally on your own machine or CI runner.
No version-control connection is required. This is often called a state-only or VCS-less workspace: Firefly creates it for you automatically the first time you run terraform init, and it appears in the Firefly console right away — before you have applied anything.
Choosing a state backend mode: This page covers local execution, where Firefly stores your state but you run Terraform yourself and the workspace is created on demand. If instead you want Firefly (or a self-hosted runner pool) to run
planandapplyfor you against a pre-created workspace, see Remote State Management. The two modes use different backend blocks (cloud {}here vs.backend "remote"there) — pick the one that matches how you want execution handled.
Overview
When you use Firefly as your backend:
Your state lives in Firefly. Every
applyuploads a new, versioned copy of your Terraform state. You can browse state versions and serials in the console.Execution stays local. Firefly does not run Terraform for you in this mode.
planandapplyexecute wherever you run them; only the resulting state is sent to Firefly. The workspace's execution mode is thereforelocal.Locking is handled for you. Concurrent
applys are serialized through Firefly's state lock, exactly as with any Terraform remote backend.The workspace is created on demand. You do not pre-create anything in the UI. The first
terraform initthat references a new workspace name creates it.
When to use this
Use a state-only workspace when you want Firefly to be the source of truth for your Terraform state and to give you visibility into that state, but you want to keep driving Terraform yourself — from a laptop, a script, or an existing CI pipeline — rather than connecting a Git repository.
Prerequisites
Terraform installed (
terraform version).A Firefly account, and your account ID — a 24-character hexadecimal string. This is the value you will use for
organization. It is not your company or account display name.curlandjq(or any HTTP client) to exchange your access key for a token in Step 2.
Throughout this guide the Firefly API host is api.firefly.ai. Use that host for both the token exchange and the cloud {} block.
Step 1 — Create an access key in the console
Access keys are how you authenticate to the Firefly API from outside the browser.
In the Firefly console, go to Settings → Access Management.
Under the API Keys section, click New API Key to generate a new access key and secret key pair.
Copy the secret key immediately — it is shown only once and cannot be retrieved later. Store it somewhere safe (a password manager or secrets vault).
You now have two values:
an access key (an identifier), and
a secret key (the credential).
For more on managing keys, roles, and permissions, see Access Management & RBAC.
Step 2 — Exchange the access key for a bearer token
Terraform authenticates to Firefly with a bearer token (a JWT), not with the access key directly. You mint that token by calling the login endpoint with your key pair.
There is no
terraform loginflow for Firefly. Do not runterraform login— mint the token yourself as shown here.
The token is returned in the accessToken field (note the camelCase). The snippet above extracts it into a TOKEN shell variable.
You can check for a successful response by echoing the TOKEN variable:
The duration attribute
duration attributeduration is optional and controls how long the minted token remains valid.
Format:
<number><unit>, where the unit is one ofh(hours),d(days),w(weeks),m(months), ory(years). Examples:1h,12h,7d,2w,6m,1y.Default:
24hif you omit the field.Maximum:
1y. A request for"duration": "1y"returns a token valid for a full 365 days; omitting the field yields the 24-hour default.
Choose the shortest duration that fits your rotation cadence. A short-lived token limits your exposure if it is ever leaked — see Security and token lifecycle below. Long-lived tokens (up to a year) are convenient for stable CI systems but should be stored in a secrets manager and rotated deliberately.
Step 3 — Store the token in a Terraform credentials file
Terraform reads a per-host token from a JSON credentials file. Create one and store the token raw — do not prefix it with Bearer; Terraform adds that itself when it calls the API.
Step 4 — Tell Terraform where the credentials file is
Terraform does not automatically look for a credentials.tfrc.json in your project directory. A file of that name only has meaning at Terraform's well-known credentials location. Choose one of the following.
Option A — Point Terraform at the local file (recommended)
Set TF_CLI_CONFIG_FILE to the file you created in Step 3. This keeps the token scoped to the project directory and is ideal for CI pipelines and ephemeral environments:
Set it once per shell session; every subsequent terraform command in that shell will find the token.
Option B — Install it globally
Place the credentials at Terraform's default location so that a bare terraform init works from any directory, with no environment variable:
The file uses the exact same JSON structure as in Step 3:
Remember to chmod 600 ~/.terraform.d/credentials.tfrc.json. If you already have other hosts in that file, add api.firefly.ai alongside them rather than overwriting it.
Option C — Environment variable
Alternatively, skip the file entirely and provide the token through a host-specific environment variable. Terraform maps the host into the variable name by replacing dots with underscores:
This is convenient in CI, though the credentials file (Option A) is generally less error-prone.
Step 5 — Configure the cloud {} block
cloud {} blockIn your root module (for example main.tf), add a cloud {} block inside terraform {}:
hostnameis alwaysapi.firefly.ai.organizationis your 24-character Firefly account ID — not a display name.workspaces.nameis the exact name that will appear in the Firefly console.
Note: assigning a new workspace to a specific project through the
cloud {}block is not currently supported. Workspaces created this way are placed in your account's default (root) project. Do not set aprojectattribute insideworkspaces {}.
Step 6 — Initialize, plan, and apply
On the first init, Terraform contacts Firefly, authenticates with your token, and — if the named workspace does not yet exist — Firefly creates it automatically as a state-only workspace (execution mode local, no VCS repository attached). The workspace appears in the console immediately, before any apply.
plan and apply run entirely on your machine. On a successful apply, Terraform uploads the resulting state to Firefly and increments the workspace's state version (its serial number).
If init fails with Required token could not be found, Terraform is not seeing your credentials — revisit Step 4. (Do not run terraform login; it does not apply to Firefly.)
Step 7 — View the workspace in the console
Open the Firefly console and go to Workflows → Workspaces. Your workspace — named exactly as you set it in Step 5 — is listed. Open it to see its current state version, serial, and last-updated time.
Managing and removing a workspace
To tear down the infrastructure and remove the workspace:
Then delete the workspace itself, either from the UI or via the API. Deletion is by workspace ID:
You can find the workspace ID by resolving the workspace by name through the API.
Security and token lifecycle
Treat the minted token like any long-lived secret:
Deleting an access key does not revoke tokens already minted from it. A token is validated by its signature and expiry; the access key is consulted only when a new token is minted, never on a per-request basis. An already-issued token therefore remains valid until it expires, even after you delete the key it came from.
Prefer short durations and rotate. Minting a fresh token is cheap. Favor short-lived tokens over a single long-lived one wherever your workflow allows.
Store tokens in a secrets manager, never in source control, and restrict file permissions (
chmod 600) on any credentials file.If a token leaks, deleting the key is not sufficient — because existing tokens stay valid until expiry, a leaked long-lived token is exposed for its full lifetime. This is the strongest reason to keep durations short.
Troubleshooting
Required token could not be found on init
Terraform can't find the credentials
Apply Step 4 (TF_CLI_CONFIG_FILE, the global file, or TF_TOKEN_api_firefly_ai). Do not run terraform login.
unauthorized / HTTP 401 on init
Token expired or wrong key pair
Re-mint the token (Step 2) and refresh your credentials file
Workspace does not appear in the console
organization set to a display name instead of the account ID
Use your 24-character account ID
init cannot reach the host
Wrong or unreachable hostname
Confirm the host is api.firefly.ai and reachable from your network
Terraform errors when a project is set
Project assignment via cloud {} is not supported
Remove the project attribute from workspaces {}
Quick reference
API host
api.firefly.ai
Token endpoint
POST https://api.firefly.ai/v2/login
Login request body
{ "accessKey", "secretKey", "duration" }
Login response fields
accessToken, expiresAt, tokenType
duration format
<number><unit> — h/d/w/m/y; default 24h; max 1y
Credentials file (local)
pointed to by TF_CLI_CONFIG_FILE
Credentials file (global)
~/.terraform.d/credentials.tfrc.json
Env-var alternative
TF_TOKEN_api_firefly_ai
Delete a workspace
DELETE https://api.firefly.ai/v2/workspaces/<WORKSPACE_ID>
Related guides
Remote State Management: Use Firefly as your backend with Firefly-managed or self-hosted runner execution (managed mode).
Firefly Workflows: High-level concepts, projects, and execution options.
Authentication: Creating API key pairs and minting tokens.
Access Management & RBAC: Managing keys, roles, and permissions.
Last updated
Was this helpful?