Runbooks
Concrete, ordered procedures for running Mero TEE. They reference the real
scripts and workflows in this repository; confirm exact flags against
--help for your checked-out version before running against production.
Deploy the Phala KMS
Section titled “Deploy the Phala KMS”Deploy mero-kms-phala on a Phala Cloud CVM using a digest-pinned image and the
release’s attestation policy.
-
Verify the release assets first. Never deploy an unverified artifact:
Terminal window scripts/release/verify-kms-phala-release-assets.sh mero-kms-v<version>This checks the checksums and the cosign Sigstore bundles for the KMS release assets (attestation policies, SBOMs, manifest).
-
Deploy the container. The compose template (
scripts/kms/phala/kms-compose-template.yaml) sets the production environment. Pin the image by digest, not tag:services:mero-kms:image: ghcr.io/calimero-network/mero-kms-phala@sha256:<DIGEST>restart: unless-stoppedports:- "8080:8080"environment:LISTEN_ADDR: "0.0.0.0:8080"DSTACK_SOCKET_PATH: "/var/run/dstack.sock"CHALLENGE_TTL_SECS: "60"ACCEPT_MOCK_ATTESTATION: "false"ENFORCE_MEASUREMENT_POLICY: "true"MERO_KMS_VERSION: "<version>"MERO_KMS_PROFILE: "locked-read-only"volumes:- /var/run/dstack.sock:/var/run/dstack.sockMERO_KMS_VERSIONdrives the release-policy fetch;MERO_KMS_PROFILEselects the profile cohort. The dstack socket must be mounted or key derivation and quote generation fail. See the configuration reference for every knob. -
Confirm health. The health endpoint always returns
200once the process is up:Terminal window curl -s https://<kms-host>:8080/health# {"status":"alive","service":"mero-kms-phala"}
Configure a merod node to use the KMS
Section titled “Configure a merod node to use the KMS”Point a merod node at the KMS and pin the attestation policy, using the repo’s helper scripts.
-
Generate the client attestation config from a release tag and KMS URL:
Terminal window scripts/policy/generate-merod-kms-phala-attestation-config.sh \--profile locked-read-only \<release-tag> https://<kms-host>:8080/ ./tee-kms.tomlThe script downloads the release’s policy and produces a
[tee]config fragment (the profile defaults tolocked-read-only). -
Apply it to a node home (use
--dry-runfirst to preview):Terminal window scripts/policy/apply-merod-kms-phala-attestation-config.sh --dry-run \--profile locked-read-only \<release-tag> https://<kms-host>:8080/ /data defaultRe-run without
--dry-runto write the config into the merod home.
Probe staging (KMS or node image)
Section titled “Probe staging (KMS or node image)”Both probes are manual (workflow_dispatch) GitHub Actions workflows. They boot
a real confidential VM, exercise the full flow, and emit measurement candidates —
the same probes the release pipeline runs.
kms-phala-staging-probe.yaml. Key inputs: kms_tag (release tag, or latest),
kms_profile, instance_type (default tdx.small), service_port (default
8080), phala_public_domain_suffix, and ita_appraisal_url (Intel Trust
Authority). It deploys to Phala, verifies /attest, runs a challenge → get-key
cycle, and returns kms-policy-candidates.json + kms-app-identity.json.
node-image-gcp-staging-probe.yaml. Key inputs: profile, image_name,
image_project, admin_api_port (default 80), wait_timeout_minutes, and
ita_appraisal_url. It boots a TDX VM from the image, waits for readiness,
collects a quote, and verifies it against Intel Trust Authority.
Verify release assets
Section titled “Verify release assets”Before trusting any release, run the matching verifier (all under
scripts/release/):
scripts/release/verify-kms-phala-release-assets.sh mero-kms-v<version>scripts/release/verify-node-image-gcp-release-assets.sh mero-tee-v<version># or the combined entrypoint:scripts/release/verify-release-assets.sh <tag>Each downloads the release assets, checks SHA-256 checksums, and verifies the
cosign signatures. A non-zero exit means the release is incomplete or tampered —
do not deploy it. On a schedule, release-auditor.yaml runs the same class of
checks across recent releases automatically.
Roll a new KMS version
Section titled “Roll a new KMS version”Because the KMS fetches its policy by version and nodes re-attest on their own schedule, a version roll is a controlled restart.
-
Verify the new KMS release assets (above) and confirm the new version appears in
compatibility-catalog.jsonpaired with the node-image version your fleet runs. -
Stage and probe. Deploy the new digest to a staging CVM and run
kms-phala-staging-probe.yamlagainst it. Confirm the probe’s measurement candidates match the published policy and a staging node completeschallenge → get-key. -
Promote policy if measurements changed: the release pipeline builds the policy from probe candidates. Any change to
kms-phala-attestation-policy.<profile>.jsonis reviewed and merged before production. -
Deploy to production with the new digest and
MERO_KMS_VERSION, then restart the container. The KMS refetches its policy on startup; existing node sessions are unaffected until they re-attest. -
Confirm. Health-check the new instance and run a canary
challenge → get-keyfrom a production node before removing the old instance.
Post-release e2e
Section titled “Post-release e2e”After a Release mero-tee run completes, two workflow_run-triggered
workflows validate the published artifacts end to end:
post-release-mero-tee-node-e2e.yaml— boots fresh TDX VMs per profile and checks their measurement candidates are covered by the release’spublished-mrtds.json, independent of the KMS.post-release-kms-node-e2e.yaml— validates KMS↔node compatibility for the released version pair (scripts/release/e2e-verify-kms-node-compatibility.sh).
Incident response
Section titled “Incident response”| Symptom | Likely cause | Action |
|---|---|---|
/get-key → 503 policy_not_ready |
MERO_KMS_VERSION unset or release-policy fetch failed |
Set MERO_KMS_VERSION, confirm the release policy asset exists and is reachable, restart. |
Node key release → 403 measurement_policy_rejected / tcb_status_rejected |
Node profile ≠ KMS profile, stale policy, or outdated TCB | Align profiles; re-probe and promote a policy covering the node’s measurements. |
Key release → 500 key_derivation_failed |
dstack socket not mounted / unreachable | Verify /var/run/dstack.sock is mounted into the container. |
cargo audit advisory flagged |
Vulnerable dependency | Bump the dependency (see security-audit.yaml / CHANGELOG.md for the pattern). |
See Error handling for the full error catalog.
Next steps
Section titled “Next steps”- Error handling — every runtime error and its operator action.
- Release pipeline — how the assets these runbooks verify are produced.
- Attestation flow and Key release — the flows these procedures exercise.