Experimental feature. Confidential Compute (TEE) is experimental and under active development. Its SDL syntax, attestation API, and runtime behavior may change without notice. We encourage you to try it and share feedback, but plan for breaking changes.
This guide shows how to enable Confidential Compute (TEE) support on your Akash provider, allowing tenants to deploy workloads inside hardware-backed Trusted Execution Environments.
Prerequisites: You must have a working Akash provider with Kubernetes already deployed. See Kubernetes Setup and Provider Installation.
Hardware required: Your nodes must have TEE-capable processors, AMD EPYC (Milan or later) for SEV-SNP, or Intel Xeon (Sapphire Rapids or later) for TDX.
Do not enable LUKS (full-disk encryption) on TEE host nodes. SEV-SNP and TDX encrypt guest VM memory at the hardware level, that is the security boundary that matters for tenant workloads. LUKS on the host root filesystem adds boot-time complexity without providing additional protection.
Overview
Confidential Compute on Akash uses Kata Containers to run tenant workloads inside hardware-encrypted virtual machines. The provider automatically:
- Schedules TEE workloads onto nodes with the correct runtime class
- Injects an attestation sidecar into each confidential workload
- Proxies attestation requests from tenants to the sidecar inside the TEE
Supported Configurations
| TEE Type | Runtime Class | Hardware |
|---|---|---|
| AMD SEV-SNP | kata-qemu-snp | AMD with SEV-SNP enabled in BIOS |
| AMD SEV-SNP + GPU | kata-qemu-nvidia-gpu-snp | Above + NVIDIA CC-capable GPU |
| Intel TDX | kata-qemu-tdx | Intel with TDX enabled in BIOS |
| Intel TDX + GPU | kata-qemu-nvidia-gpu-tdx | Above + NVIDIA CC-capable GPU |
STEP 1 — Verify Hardware Support
AMD SEV-SNP
Run on each TEE node:
# Check CPU supports SEV-SNPdmesg | grep -i snpYou should see output indicating SEV-SNP is enabled:
SEV-SNP enabledVerify the device exists:
ls -la /dev/sevIf SEV-SNP is not showing: Enable it in your BIOS/UEFI under AMD CBS > CPU Configuration > SEV-SNP. Ensure your firmware is up to date.
Intel TDX
Run on each TEE node:
# Check CPU supports TDXdmesg | grep -i tdxYou should see:
tdx: TDX module initializedvirt/tdx: module initializedVerify the device exists:
ls -la /dev/tdx_guest # or /dev/tdx-attest on older kernelsIf TDX is not showing: Enable it in your BIOS/UEFI under Intel Advanced Menu > TDX. Requires a TDX-capable kernel (Linux 6.2+).
STEP 2 — Install Kata Containers via kata-deploy
Kata Containers provides the confidential VM runtime. Install it using the kata-deploy Helm chart, which configures containerd runtime classes, RuntimeClass resources, and all Kata binaries automatically.
Do not install QEMU, KVM userspace, libvirt, or OVMF packages on the host. Kata ships its own NVIDIA-patched versions of these components. Pre-installing them creates silent conflicts.
helm install kata-deploy \ oci://ghcr.io/kata-containers/kata-deploy-charts/kata-deploy \ --namespace kata-system --create-namespace \ --set nfd.enabled=false \ --wait --timeout 10m \ --version 3.29.0If running K3s instead of standard Kubernetes, add
--set k8sDistribution=k3s. Without this flag, kata-deploy will fail searching for containerd config at the wrong path.
Verify the installation:
# kata-deploy pod should be Runningkubectl get pods -n kata-system
# RuntimeClasses should be created automaticallykubectl get runtimeclass | grep kata-qemuYou should see runtime classes including kata-qemu-snp, kata-qemu-tdx, and their GPU variants (kata-qemu-nvidia-gpu-snp, kata-qemu-nvidia-gpu-tdx).
STEP 3 — Install NVIDIA GPU Operator (GPU providers only)
Skip this step if your provider does not offer GPU Confidential Computing.
The NVIDIA GPU Operator handles GPU VFIO binding, CC mode toggling, and device plugin registration. Do not install NVIDIA GPU drivers on the host — the operator manages everything.
helm repo add nvidia https://helm.ngc.nvidia.com/nvidiahelm repo update
helm install gpu-operator nvidia/gpu-operator \ --namespace gpu-operator --create-namespace \ --version v26.3.1 \ --set sandboxWorkloads.enabled=true \ --set sandboxWorkloads.mode=kata \ --set nfd.enabled=true \ --set nfd.nodefeaturerules=true \ --wait --timeout 10mLabel each GPU node for operand activation:
kubectl label node <node-name> nvidia.com/gpu.workload.config=vm-passthroughVerify the installation:
# All operand pods should be Runningkubectl get pods -n gpu-operator
# GPU should be bound to vfio-pci (not nvidia driver)lspci -nnk -d 10de: | grep "Kernel driver in use"# Expected: vfio-pci
# CC mode should be enabledkubectl get node <node-name> -o json | \ jq '.metadata.labels | with_entries(select(.key | startswith("nvidia.com/cc")))'# Expected: "nvidia.com/cc.mode.state": "on", "nvidia.com/cc.ready.state": "true"
# Passthrough GPU resource should be advertisedkubectl get node <node-name> -o json | \ jq '.status.allocatable | with_entries(select(.key | startswith("nvidia.com")))'# Expected: "nvidia.com/pgpu": "1" (or more, depending on GPU count)The operator deploys several components:
- nvidia-vfio-manager — binds GPUs to the
vfio-pcidriver for passthrough - nvidia-cc-manager — toggles GPU Confidential Computing mode (default: on)
- nvidia-kata-sandbox-device-plugin — advertises
nvidia.com/pgpuresources - nvidia-sandbox-validator — node-level CC readiness validation
- NFD components — detects CPU TEE capabilities and GPU presence via node labels
STEP 3b — Label Nodes for TEE Platform Detection
The Akash provider detects the TEE platform at startup by scanning Kubernetes node labels. Standard NFD (Node Feature Discovery) labels like feature.node.kubernetes.io/cpu-security.sev.snp.enabled are not sufficient. The provider looks for platform-specific labels in a dedicated namespace.
Apply the appropriate label to every TEE-capable node:
AMD SEV-SNP
kubectl label node <node-name> amd.feature.node.kubernetes.io/snp=trueIntel TDX
kubectl label node <node-name> intel.feature.node.kubernetes.io/tdx=trueWhy not use standard NFD labels? The provider needs a single, unambiguous signal per platform. NFD exposes many granular CPU feature labels (
SEV,SEV_ES,SEV_SNP,SME, etc.) but none in the format the provider expects. These dedicated labels act as a provider-level opt-in that confirms the node is fully configured for CC workloads, not just that the CPU has the capability.
Verify the labels were applied:
kubectl get nodes --show-labels | grep -E "amd.feature|intel.feature"STEP 4 — Configure Provider Values
The Akash provider can inject an attestation sidecar into confidential workloads that request it. This sidecar runs inside the TEE and serves hardware-signed attestation reports to tenants. Configure it through the provider Helm values.
Helm values
| Value | Description | Required |
|---|---|---|
attestation.enabled | Enables the mutating admission webhook that injects the attestation sidecar into confidential workloads. | Yes |
attestation.sidecarImage.repository | Container repository for the attestation sidecar. | Yes |
attestation.sidecarImage.tag | Container tag. When empty, defaults to the provider chart app version. | No |
attestation.webhookPort | HTTPS port used for Kubernetes admission callbacks. Defaults to 9443. | No |
Add these values to provider.yaml:
attestation: enabled: true webhookPort: 9443 sidecarImage: repository: ghcr.io/akash-network/provider-attestation-sidecar tag: ""Leave the tag empty to keep the sidecar aligned with the provider chart app version. Only set an explicit tag when you have verified that it is compatible with the provider version.
STEP 5 — Configure Provider Attributes
Tenants discover TEE-capable providers through the on-chain tee/type attribute. The provider detects the hardware platform from the Kubernetes node labels configured in Step 3b; do not publish a separate tee/platform attribute.
CPU only
attributes: - key: tee/type value: cpuCPU with confidential GPU
attributes: - key: tee/type value: cpu-gpuAfter updating attributes, restart your provider:
cd /root/providerhelm upgrade akash-provider akash/provider \ -n akash-services \ --version 19.0.2 \ -f provider.yaml \ --set bidpricescript="$(cat price_script.sh | openssl base64 -A)"STEP 6 — Verify Setup
Test with a Confidential Deployment
Create a test SDL file (test-cc.yaml):
---version: "2.1"
services: web: image: nginx expose: - port: 80 as: 80 to: - global: true params: tee: type: sev-snp
profiles: compute: web: resources: cpu: units: 0.5 memory: size: 256Mi storage: size: 128Mi placement: akash: pricing: web: denom: uact amount: 1000
deployment: web: akash: profile: web count: 1Deploy and verify:
# Deploy through the selected providerakt deploy test-cc.yaml \ --from <your-key> \ --bid-select "provider=<provider-address>" \ --yes
# After lease is created, check that the pod has the correct runtime classkubectl get pods -n <lease-namespace> -o jsonpath='{.items[0].spec.runtimeClassName}'# Expected: kata-qemu-snp
# Check the attestation sidecar was injectedkubectl get pods -n <lease-namespace> -o jsonpath='{.items[0].spec.containers[*].name}'# Expected: web akash-attestation-sidecarRequest an Attestation Quote
AKT_FROM=<your-key> akt provider lease-attestation \ <deployment-sequence> \ --provider <provider-address>A successful response confirms that the provider returned an attestation payload over an authenticated lease connection and that the request nonce is fresh. akt does not currently validate the evidence signature, endorsement chain, or measurement policy, so treat the response as evidence to pass to a TEE verifier rather than proof by itself that the workload is running on genuine TEE hardware.
Troubleshooting
Provider not bidding on CC workloads
The provider won’t bid on TEE deployments if it can’t detect the TEE platform at startup. Check the provider logs for detected TEE platform:
kubectl logs akash-provider-0 -n akash-services | grep -i "tee platform"If you see no output or TEEPlatformNone, the node labels are missing. Apply them per Step 3b and restart the provider pod.
Pod stuck in Pending
kubectl describe pod <pod-name> -n <lease-namespace>Common causes:
- RuntimeClass not found: Verify the RuntimeClass exists with
kubectl get runtimeclass - No TEE-capable nodes: Ensure nodes with TEE hardware are labeled and schedulable
- Kata not installed: Check that Kata is properly installed on the target node
Insufficient nvidia.com/gpu: The provider setnvidia.com/gpuinstead ofnvidia.com/pgpu. This means TEE platform detection failed, see the section above
Attestation sidecar not injected
- Verify the webhook is running:
kubectl get mutatingwebhookconfigurations - Check provider logs for webhook errors
- Ensure
attestation.enabled: trueis present inprovider.yamland was applied with the Helm upgrade
Attestation quote returns error
- Verify the sidecar container is running:
kubectl logs <pod> -c akash-attestation-sidecar -n <namespace> - Check that TEE devices are accessible inside the Kata VM
- For GPU variants, verify NVIDIA drivers are available inside the guest
SEV-SNP device not found
- Ensure BIOS has SEV-SNP enabled
- Update to latest firmware/microcode
- Verify kernel supports SEV-SNP (Linux 5.19+)
- Check
dmesg | grep -i sevfor errors
TDX device not found
- Ensure BIOS has TDX enabled
- Verify TDX kernel module is loaded:
lsmod | grep tdx - TDX requires Linux 6.2+ with TDX support compiled in
Related Topics
- Confidential Compute Overview — Tenant-facing guide for deploying confidential workloads
- SDL Advanced Features — SDL reference for TEE configuration
- GPU Support — Enable GPU resources on your provider
- Provider Attributes — Advertise provider capabilities
- Provider Installation - Base provider setup