This guide walks you through deploying a Morpheus TEE-hardened provider node on SecretVM (SCRT Labs’ confidential VM platform). By the end you’ll have a provider running inside a hardware-secured Intel TDX enclave that consumers can cryptographically verify before sending prompts. For deeper details (cosign verification, RTMR3 recomputation, attestation manifest inspection) see TEE reference. For the trust-chain conceptual picture see TEE overview.

What you’ll need

  • A funded wallet with MOR + ETH on Base Mainnet (or Base Sepolia for testnet).
  • The wallet’s private key — this stays encrypted inside the TEE.
  • An RPC endpoint for Base Mainnet (e.g. wss://base-mainnet.g.alchemy.com/v2/<your_key>).
  • Your AI model backend reachable via a private URL (e.g. http://my-model:8080/v1/chat/completions).
  • A SecretVM account at https://secretai.scrtlabs.com — sign up to get an API key.
  • (Recommended) secretvm-cli: sudo npm install --global secretvm-cli.

Step 1: Get the Docker Compose file

Each CI/CD build produces a deployed compose file pinning the TEE image by SHA-256 digest — that’s what SecretVM uses to compute RTMR3. Download docker-compose.tee.deployed.yml from the latest GitHub Release — the digest is already filled in. You can also use the template at proxy-router/docker-compose.tee.yml and replace the image tag yourself. The compose includes a Traefik TLS sidecar that uses SecretVM’s auto-generated certs to serve the API on HTTPS port 443. The full compose body is reproduced in TEE reference → Step 1.
Use the digest-pinned version. Tags like :latest are mutable; the digest is not. Using the digest ensures RTMR3 will match the CI/CD-computed golden value.

Step 2: Prepare your secrets

Create a .env file with your 5 provider-specific secrets:
WALLET_PRIVATE_KEY=<your_private_key>
ETH_NODE_ADDRESS=wss://base-mainnet.g.alchemy.com/v2/<your_alchemy_key>
MODELS_CONFIG_CONTENT={"models":[{"modelId":"0x<your_model_id>","modelName":"your-model-name","apiType":"openai","apiUrl":"http://your-model:8080/v1/chat/completions","concurrentSlots":6,"capacityPolicy":"simple"}]}
WEB_PUBLIC_URL=https://your-public-domain.com
COOKIE_CONTENT=admin:<your_secure_password>
MODELS_CONFIG_CONTENT must be single-line JSON. Schema: models-config.json.

Step 3: Deploy on SecretVM

  1. Go to https://secretai.scrtlabs.com/secret-vms/create
  2. Docker Compose: paste the contents of your compose file.
  3. Encrypted Secrets: enter your 5 variables.
  4. Advanced features:
SettingRecommendedNotes
PlatformIntel TDXRequired to match CI/CD golden values
Additional FilesEmptyAdding files changes RTMR3
Enable PersistenceOnPreserves data across reboots
Enable UpgradesOnAllows updates without reprovisioning
Hide Runtime InfoOffKeeps the /docker-compose endpoint accessible for verification
  1. Click Deploy.

Step 4: Verify the node is running

Once provisioned (typically 2-3 minutes):
curl https://<your-secretvm-url>/healthcheck
The API is served on HTTPS port 443 via Traefik. Expected:
{ "status": "healthy", "version": "v7.0.0", "uptime": "1m30s" }
Verify the attestation endpoint (separate port, direct from SecretVM):
curl -k https://<your-secretvm-url>:29343/cpu | head -c 100
Returns a long hex string — your hardware-signed TDX attestation quote.

Step 5: Register as a TEE provider

Same flow as a standard provider, with one critical addition: tag your model tee.
1

Open Swagger

https://<your-secretvm-url>/swagger/index.html
2

Approve, register, bid

Follow Register on chain. When creating the model, include the tag "tee" in the tags array.
The tee tag is what triggers consumer-side attestation verification. Without it, consumers treat you as a standard provider.

Step 6: Verify your attestation

Quick check (SecretVM portal)

  1. Go to https://secretai.scrtlabs.com/attestation
  2. Paste your compose file contents.
  3. Enter your VM URL.
  4. Click Verify.
Three layers must pass: hardware (genuine Intel TDX), VM (known SecretVM firmware/kernel), software/RTMR3 (your image + compose match what CI/CD built).

Programmatic check (cosign)

cosign verify \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity-regexp 'MorpheusAIs/Morpheus-Lumerin-Node' \
  ghcr.io/morpheusais/morpheus-lumerin-node-tee:<your-version>

cosign verify-attestation \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity-regexp 'MorpheusAIs/Morpheus-Lumerin-Node' \
  --type https://morpheusais.github.io/tee-attestation/v1 \
  ghcr.io/morpheusais/morpheus-lumerin-node-tee:<your-version> \
  2>/dev/null | jq -r '.payload' | base64 -d | jq '.predicate'

What consumers see, what your P-Node does

The two-hop trust chain — see TEE overview for the full conceptual breakdown.
C-Node (v6.0.0+) ─Phase 1─▶ P-Node (-tee, v7.0.0+) ─Phase 2─▶ Backend LLM (SecretVM)
  • Phase 1 (consumer ↔ your P-Node): the consumer’s proxy-router fetches your :29343/cpu quote, verifies via SecretAI portal, checks TLS binding, compares RTMR3 against the cosign-signed golden values, and re-checks with a ~50 ms fast path on every prompt.
  • Phase 2 (your P-Node ↔ backend): your P-Node fetches the backend’s :29343/cpu, pins TLS, replays workload RTMR3 from :29343/docker-compose, verifies GPU evidence via NVIDIA NRAS, and re-checks per prompt. Per-model state is exposed at GET /v1/models/attestation.
Forward compatibility: a v6.0.0+ C-Node only needs to understand Phase 1; Phase 2 is your P-Node’s job. Any v6+ consumer works with any v7+ provider, gaining Phase 2 transparently.

Troubleshooting

SymptomLikely causeFix
Healthcheck returns nothingVM still provisioningWait 2-3 min, check secretvm-cli vm list
Attestation quote emptyPort 29343 not exposedSecretVM exposes it automatically — check VM status
RTMR3 mismatchWrong compose content or rootfs versionUse the exact deployed compose from CI/CD artifacts (byte-for-byte)
TLS binding failsUsing a proxy/CDN that terminates TLSThe consumer must connect directly — no TLS-terminating intermediaries on :29343
tee model not getting sessionsConsumers on older versionsConsumers need v6.0.0+ for Phase 1
Phase 2 failing silently on consumerPhase 2 runs in your P-NodeCheck GET /v1/models/attestation on your node

Updating your node

secretvm-cli -k <your_api_key> vm edit <your_vm_uuid> \
  --docker-compose path/to/new/docker-compose.tee.yml
The VM reboots with the new image. Verify with /healthcheck and the attestation portal.

Further reading