Configure runners and Terraform state#
Every Deployment needs one customer-owned runner and one customer-owned Azure Blob state location. Reply CMP guides the setup from the Deployment and prevents Plan or Apply until both are ready.
Navigate: Provisioning → Deployments → select a Deployment → Runner & state.
The page shows at a glance whether the runner, callback identity and state are ready.#
What the three connections do#
The setup uses three different trust paths. Keeping them separate limits the impact of each credential.
Purpose |
Selected in Reply CMP |
Used for |
|---|---|---|
Dispatch |
Azure DevOps or GitHub credential |
Start only the configured pipeline or workflow. |
Infrastructure and state |
Azure workload identity owned by the customer |
Run Terraform against Azure and access the selected Blob container. AWS and GCP use their own runner identities. |
Reply CMP callback |
Tenant claim identity managed by Reply CMP |
Claim the operation and report status and evidence with a short-lived token. |
The dispatch secret is stored in the tenant vault and never reaches Terraform. Infrastructure, state and callback access use workload identity federation; no shared API token or storage key is required.
Reuse an existing setup#
Select Reuse setup when another Deployment in the same tenant already uses the intended runner and Storage account.
Reply CMP copies the editable configuration into the new Deployment. Review it, validate the container and save. The new Deployment receives its own state key, state lock and operation history; it never shares another Deployment’s state file.
Configure Azure DevOps#
Download and commit the Azure DevOps starter ZIP before configuring the Deployment.
Prepare Azure DevOps#
Create an Azure Resource Manager service connection using workload identity federation.
Grant its identity access to the target Azure resources and
Storage Blob Data Contributoron the state container.Create a pipeline from
azure-pipelines.ymland note its numeric definition ID.Keep
REPLY_CMP_EXPECTED_API_BASE_URLcommitted inazure-pipelines.yml. The downloadable production starter already pinshttps://apis.welkincmp.com.Store an Azure DevOps PAT under Module registry → Credentials. It must be able to queue the pipeline, manage Service Connections and manage protected pipeline-resource permissions in that project.
The trust pin is not a secret. It prevents a dispatched operation from redirecting the runner to another control plane. Change it only when Reply CMP support provides an explicit non-production endpoint.
The state container may be in another subscription in the same Microsoft Entra tenant. Grant the service-connection identity access in that subscription; the runner selects the signed state subscription before validating and opening the backend.
Complete the Runner panel#
Select Change runner, choose Azure DevOps pipeline, then:
select the Azure DevOps credential;
select or type the organisation URL, project and numeric pipeline ID;
select or type the Terraform Azure service connection;
under Secretless Reply CMP callback, select Create connection;
wait for the green connected status, then select Use runner.
The organisation URL begins with https://dev.azure.com/. Project, pipeline and service-connection dropdowns are editable: type the exact value when discovery is unavailable.
The infrastructure connection runs Terraform; the green callback connection reports operation status to Reply CMP.#
Reply CMP creates one convention-based tenant claim identity and reuses it across the tenant. The UI shows Claim identity ready; customers do not manage its app registration or create a client secret.
If the callback connection already exists and matches the selected project and tenant identity, Reply CMP verifies and reuses it. If automatic creation fails, the panel reveals Create the connection manually with copy-ready values:
open Azure DevOps → Project settings → Service connections → New service connection;
choose Azure Resource Manager;
choose the manual app-registration option and Workload identity federation;
copy the Environment, scope, Application ID, Directory ID and connection name shown by Reply CMP;
leave access for all pipelines disabled and save as a draft;
return to Reply CMP and select Connect existing.
Reply CMP completes federation and authorises only the selected pipeline.
Configure GitHub Actions#
Download and commit the GitHub starter ZIP.
Prepare GitHub#
Create a protected GitHub Environment for the runner.
Add Environment variables
AZURE_CLIENT_ID,AZURE_TENANT_IDandAZURE_SUBSCRIPTION_IDfor the customer Azure workload identity.Add the federated credential that lets this Environment and protected ref use that Azure identity.
Keep
id-token: writeandcontents: readin the workflow.Keep the committed production trust pin
REPLY_CMP_EXPECTED_API_BASE_URL: https://apis.welkincmp.comunchanged unless Reply CMP support provides another environment endpoint.Store a fine-grained GitHub token or GitHub App credential in Module registry → Credentials with permission to dispatch the selected workflow.
Complete the Runner panel#
Select Change runner, choose GitHub Actions, then enter:
repository owner and name;
workflow path
.github/workflows/reply-cmp-provisioning.yml;protected branch or tag;
protected GitHub Environment;
the GitHub dispatch credential.
Reply CMP creates or repairs the tenant claim identity and its GitHub federation for the protected repository context. The callback identity needs no subscription role. Select Use runner when the panel is ready.
Connect existing Terraform state#
Reply CMP does not create a Storage account or container. Prepare them through your normal cloud process, then select Change state.
Select an active Azure Connection. Reply CMP uses it only through Azure management APIs to list and validate Storage resources.
Select the resource group.
Select the Storage account.
Select the existing private Blob container reserved for Terraform state.
Check State authentication. It shows the identity the runner will use:
Azure DevOps uses the selected Terraform Azure service connection;
GitHub uses the Azure identity configured on the protected Environment.
Select Validate storage. This checks the account, container and protection settings through the selected Azure Connection.
Correct any failed control, validate again and select Use state.
Select Save configuration on the Runner & state page.
Start Plan. Before Terraform runs, the runner signs in with the infrastructure identity, writes a disposable probe Blob, acquires and releases a lease, then deletes the probe. Plan stops before Terraform if this live access test fails.
Reply CMP validates the container without reading or proxying Terraform state.#
Save-time validation requires:
secure HTTPS traffic only;
Microsoft Entra authentication only;
anonymous Blob access disabled and a private state container;
TLS 1.2 or later;
Blob versioning;
at least 14 days of Blob and container soft delete;
The runner preflight separately requires Blob read, write, delete and lease access for the infrastructure identity. Storage Blob Data Contributor is sufficient; Storage Blob Data Owner also works but grants more access than the runner needs. This live check cannot be completed by the browser or by the Azure Connection used for discovery because it must use the exact workload identity selected in the customer runner.
The Storage account may expose either a public endpoint or a private endpoint. Reply CMP does not impose a network topology. A Microsoft-hosted runner can use a reachable public endpoint; a private endpoint or restrictive firewall requires a runner with the corresponding network path. Public network reachability never enables anonymous state access: Microsoft Entra authentication and the private container remain mandatory.
Reply CMP generates the state key and shows it read-only. Do not create or enter a state key, storage key, SAS token or connection string.
State locking and later changes#
The state subscription, resource group, account, container and generated key become immutable before the first potentially mutating successful Apply. This prevents a later edit from silently pointing Terraform at another state file.
Runner settings can still be changed when a pipeline, workflow or workload identity is replaced. A locked state move is a controlled migration, not a normal edit.
AWS and GCP Resources#
Azure Blob remains the Deployment state backend when Resources also target AWS or GCP. Configure the AWS or Google Cloud workload identity in the customer runner before Terraform starts. Do not enter AWS access keys or Google service-account keys in Reply CMP.
Review the first Plan carefully and confirm that every provider alias targets the intended account, subscription, project and region.
Adopt an existing Deployment#
An existing Deployment already has live cloud resources. Connecting an empty state container does not import them and must not cause Terraform to recreate them.
When the old Terraform state is available and trustworthy, migrate the complete state file:
stop all old pipelines and freeze Deployment changes;
back up the old state and record its version or checksum;
configure the new runner and container in Reply CMP, then copy the old state to the exact deterministic key displayed under Runner & state;
keep the same module versions, provider aliases and Resource inputs used by the old Deployment;
start Plan and require
0creates,0deletes and0replacements;review any expected in-place metadata change;
start Apply only after the state-backed Plan is safe, then run one final Plan and require zero drift.
If the old state is missing an individual object, Plan returns state-adoption-required with the stable Terraform address. Use a reviewed one-time migration job to run terraform import for that exact address and provider-specific object ID. Run Plan again before Apply.
Warning
Never bypass state-adoption-required, delete a live object to make the error disappear or copy one state file into several Deployments. Keep the old state and runner frozen until the final zero-drift Plan succeeds.
Before the first Plan#
Confirm all of the following:
Runner and Terraform state both show ready or validated status.
The callback card is green and identifies the expected connection.
The infrastructure identity can reach the target cloud and state container.
The runner can reach the Reply CMP API and Blob endpoint.
The committed endpoint trust pin matches the Reply CMP environment.
The runner uses Terraform
1.15.8and the current starter scripts.