Skip to main content
The Murmur Terraform provider, prassoai/murmur, manages your tenant’s catalog from Terraform. Every resource you would write with murmur set (a workspace, a placement, an agent persona, a tenant binding) becomes a murmur_catalog_resource that you review in a plan and apply like any other infrastructure. The provider’s attribute reference is on the Registry. This guide shows how the pieces fit together.

Install the provider

terraform init downloads the provider from the Registry and records its checksums in .terraform.lock.hcl. Commit that file. auth chooses who Terraform acts as. Shared configurations and CI apply as a service profile. To try the provider from your own machine, apply as yourself.

Apply as yourself

With auth = "gh", Terraform calls Murmur as you, with exactly the permissions you hold, using the GitHub CLI’s login on the machine running Terraform:
Use it for a first plan from your own machine. Tenants that sign in with Google apply as a service profile.

Apply as a service profile

A service profile is a non-human identity. Terraform authenticates as one with an API key, and the profile holds exactly the permissions the configuration needs. An organization admin sets it up once.

1. Create the service profile

A name and description are all the profile needs: Terraform uses it to read and write catalog resources.

2. Grant it the permissions the configuration needs

Grant the profile its permissions with a tenant binding that names the profile as service-profile:terraform. Each Terraform operation needs one permission on the resource’s kind: Two cases need a second permission:
  • Updating a workspace’s grants also needs workspace.administer, checked against the grants saved before the change. The binding below includes it.
  • A resource named {workspace}/{slug} lives inside a workspace and also needs workspace.use on that workspace. A workspace’s own grants confer it: the suggested defaults give it to every service profile through service-profile:*. For a workspace whose grants leave that out, name service-profile:terraform in them.
List each kind your configuration manages. For workspaces, placements, and agent personas:
List each verb Terraform uses. In a tenant binding, workspace.* also confers workspace.use on every workspace, including those whose grants leave the profile out.

3. Create an API key for the profile

Go to Organization Settings → Automations → API Keys, click Create API key, and choose the terraform service profile. The full key, starting mur_, is shown once. See API keys for the full steps.

4. Apply with the key

Store the key as the MURMUR_API_KEY secret of the CI system that runs Terraform, and keep auth = "api_key" in the provider block:
Run terraform plan on pull requests and terraform apply on merge, and keep state in a remote backend. Restrict access to that state as you would to the catalog itself: it holds a copy of every resource it manages. The provider also accepts the key inline as api_key. Prefer the environment variable, which keeps the key out of configuration.

Manage catalog resources

Each resource names a kind and a name, plus its body. JSON-backed kinds take payload; markdown-backed kinds such as agent-persona take markdown:
payload is compared as parsed JSON, so a plan shows changed values and ignores key order and formatting. The files hold the same YAML you would pipe to murmur set. To manage a whole directory of them with two resources and for_each, see Managing a Catalog from Files on the Registry. Every workspace that bakes or rolls out images should set ignore_fields = ["imageRef"]. The first apply still needs an imageRef in the payload; after that, Terraform keeps whatever image the workspace is running. Set secrets with murmur secret set. Terraform state is stored in plaintext, so the provider rejects credential-bearing kinds such as secret.

Infrastructure and placement in one configuration

The customer placement modules emit a ready-made placement output. Feed it to the provider instead of piping it through the CLI, and the cloud resources, the placement, and the workspace that uses it all come from one apply:
The workspace refers to the placement resource, so Terraform creates the placement first. The AWS module (modules/aws-wif) emits the same placement output. Baking the image the workspace runs is still a murmur bake; see step 3 of the placement guide for GCP or AWS.

Bring existing resources under Terraform

Resources you already created with the CLI or dashboard can be imported by <kind>/<name>:
Or declare it in configuration:
Import reads the live resource. A resource created with the CLI or dashboard gets one update in its next plan: the claim that makes Terraform its owner (managed_by becomes terraform). Apply it; after that the plan is empty.

Who owns a resource

Each resource has one writer. Once Terraform manages it, an edit in the dashboard or CLI shows up as drift on the next plan, and applying writes the Terraform value back. If another system manages the resource, the apply fails and names that system; set force_ownership = true for a single apply to take it over. Every write is conditional on the version Terraform last saw. If someone changes a resource between your plan and your apply, the apply fails with a conflict and leaves their change in place. Run terraform plan again to review it.