1.0 Introduction
This article describes how to deploy and run Confidential Containers (CoCo) using Fortanix Confidential Computing Manager (CCM) and Fortanix Data Security Manager (DSM).
The solution is based on the open-source CNCF Confidential Containers (CoCo) and Kata Containers projects, with Fortanix components integrated on top. It runs containerized applications in a confidential computing environment. Fortanix DSM protects the encryption keys used to encrypt the container image, while Fortanix CCM verifies the confidential workload through remote attestation.
2.0 Definitions
Fortanix Node Agent - The Fortanix Node Agent software enables the registration of compute nodes to CCM when installed on a compute node. It assists in the verification of hardware and platform software running on compute nodes and application attestation.
Container Registry: A repository used to store and distribute container images. In this guide, the container registry stores the encrypted container image and makes it available to the Kubernetes environment for deployment.
TEE (Trusted Execution Environment): A hardware-isolated environment that protects code and data during execution from unauthorized access, including access from the host operating system.
Confidential Containers (CoCo): An open-source technology for running Kubernetes pod in confidential computing environments.
Kata Containers: The runtime environment used by Confidential Containers to provide a VM-based isolation for containers.
ccm_as: A Fortanix Attestation Service module implemented in the CoCo Attestation Agent (AA) that collects TEE (Trusted Execution Environment) attestation evidence, performs attestation with Fortanix CCM, and obtains the application certificate issued by CCM.ccm_kbc: A Fortanix Key Broker Client (KBC) module implemented in the Confidential Data Hub (CDH) that communicates with Fortanix DSM for secure key operations.Key Encryption Key (KEK): A key stored and managed in Fortanix DSM that protects encryption keys used for the container image.
Layer Encryption Key (LEK): The key used for the container-layer encryption operation. The LEK remains protected and non-exportable in Fortanix DSM.
Mutual TLS (mTLS): A TLS authentication mechanism in which both the client and server authenticate each other using certificates.
Fortanix Data Security Manager (DSM): A platform that provides centralized key management and cryptographic operations for protecting data. In this guide, DSM securely stores the non-exportable KEK and performs the required key operation to unwrap the LEK used to decrypt the protected container image.
Fortanix Confidential Computing Manager (CCM): A centralized control plane for managing and attesting confidential workloads. In this guide, CCM verifies the measurements of the confidential workload and, after successful attestation, issues a short-lived X.509 application certificate used by the workload to authenticate to DSM.
Fortanix CoCo Encryption Tool: A tool (
coco-keyproviderDocker image) used to encrypt container images. It uses Fortanix DSM to protect the encryption key used to encrypt the container image.Fortanix CoCo Helm Chart: A Helm chart used to install and configure the Kata artifacts required to run Confidential Containers in a Kubernetes environment, including the image, kernel, and runtime class configuration. The CoCo AA integrated with the
ccm_asmodule and the CDH integrated with theccm_kbcmodule are embedded in the Kata guest image.
3.0 Prerequisites
Before deploying Confidential Containers, ensure that the required hardware, software, and Fortanix services are available.
3.1 Hardware and Software Requirements
You will require a Linux machine to containerize the application and create the encrypted container image. The machine is recommended to meet the following minimum requirements:
COMPONENT | MINIMUM REQUIREMENT |
|---|---|
CPU | 16 cores |
Memory | 128 GB |
Disk | More than 100 GB
|
Operating System | Ubuntu 24.04 LTS |
Required software |
|
3.2 Networking Requirements
The machine must have network access to Fortanix DSM to perform the required key operations during container image encryption.
Protocol: HTTPS
Port: 443
Destination: DSM endpoint URL
DSM SaaS: Use the endpoint of your DSM region.
DSM on-premises: Use the appropriate DSM endpoint configured.
3.3 Confidential Computing Host Requirements
The end user requires a Confidential Computing Host, which is a bare-metal host with hardware and platform support for confidential computing. The host must support Advanced Micro Devices (AMD) Secure Encrypted Virtualization – Secure Nested Paging (SEV-SNP) platform.
The host must be configured with the required hardware, firmware, operating system, kernel, and confidential-computing prerequisites to support launching confidential VMs.
For NVIDIA-validated hardware configurations, refer to the supported hardware tables for AMD SEV-SNP here.
NOTE
The Fortanix CoCo Helm chart does not configure the host kernel, firmware, or other host-level confidential-computing settings. Complete these host-level prerequisites before installing the Fortanix CoCo Helm Chart.
The following AMD SEV-SNP environments are supported:
COMPONENT | SUPPORTED CONFIGURATION |
|---|---|
CPU | AMD SEV-SNP |
Host OS | Ubuntu 26.04.1 LTS |
Host kernel | 6.17.0 |
Operating System | Ubuntu 24.04 LTS |
GPU | NVIDIA Hopper, NVIDIA Blackwell, RTX PRO6000 |
For more information, refer to Supported Platforms.
3.4 Kubernetes Requirements
You must have a Kubernetes cluster installed on the confidential computing host before installing the Confidential Containers components.
The following Kubernetes software versions are supported:
COMPONENT | SUPPORTED CONFIGURATION |
|---|---|
Kubernetes | 1.24 or later |
Containerd | 1.7 or later |
Helm | 3.8 or later |
SELinux | Disabled |
1 Node | At least one node with the node.kubernetes.io/worker label |
NOTE
Kind and Minikube are not recommended for this deployment because QEMU is known to be incompatible with these cluster environments. Fortanix recommends using kubeadm for setting up the Kubernetes cluster.
Reference: https://confidentialcontainers.org/docs/getting-started/prerequisites/software/
4.0 Architecture

Figure 1: Architecture flow
4.1 Architecture Flow
The following steps describe the end-to-end process for deploying an encrypted application or model as a Confidential Container using Fortanix CCM, Fortanix DSM, and NVIDIA GPU.
Containerize the Application: Containerize the application or model for deployment in the confidential environment. Refer to Section 3.1: Hardware and Software Requirements.
Configure DSM for Secure Key Release: Configure the DSM account to securely release the cryptographic keys required to access the protected container image. For detailed instructions, refer to Section 6.0: Configure Fortanix DSM.
Encrypt the Container Image: Encrypt the container image using the Fortanix Encryption Tool, which uses DSM to protect the application or model. For detailed instructions, refer to Section 7.0: Prepare the Encrypted Container Image.
Publish to the Container Registry: Push the encrypted container image to a container registry accessible by your Kubernetes environment. For detailed instructions, refer to Section 7.0: Prepare the Encrypted Container Image.
Configure CCM: Configure the CCM application for application registration, node enrollment, and attestation. For detailed instructions, refer to Section 5.0: Configure Fortanix CCM.
Prepare the Confidential Environment: Configure the Kubernetes environment on a supported TEE platform, such as AMD SEV-SNP. For more information, refer to Section 8.0: Prepare the Confidential Computing Environment.
Register Application Measurements: Register the application measurements required for CCM to verify the confidential workload. For detailed instructions, refer to Section 9.0: Register Application Measurements with CCM.
Deploy the Confidential Container: Configure and deploy the encrypted container image using Kubernetes. For detailed instructions, refer to Section 10.0: Deploy the Confidential Container.
Attest and Run the Workload: Attest the workload and, after successful attestation and authentication with DSM, run the application or model inside the confidential environment.
5.0 Configure Fortanix CCM
Configure Fortanix CCM to register the confidential workload, enroll the compute node, and enable workload attestation.
5.1 Create an Account
A Fortanix Armor account is the top-level container for Fortanix CCM, builds, and nodes. An account is generally associated with an organization, rather than an individual. Different accounts are fully isolated from each other.
To get started with Fortanix CCM you must first sign up on Fortanix Armor and create an account. If you already have an existing account, log in to that account.
For more information on how to sign up, log in, and create a Fortanix Armor account, refer to Getting Started with Fortanix Armor.
5.2 Create a Group
In Fortanix CCM, a group is a collection of users and objects that helps users manage identities, create collaborating groups, and organize and secure applications, datasets, and workflows that belong to the group.
Create a Fortanix Armor IAM group. For detailed instructions, refer to Fortanix Armor Identity and Access Management.
5.3 Download Zone CA Certificate from your Fortanix CCM Account
NOTE
You must download the Zone CA Certificate from your Fortanix CCM account for upload to the Fortanix DSM account to enable Secure Key Release (SKR) functionality. The SKR feature ensures that cryptographic keys are released from Fortanix DSM only when the application proves it is running in a trusted and secure environment, thereby protecting both the data and model.
Perform the following steps to download the Zone CA Certificate from your Fortanix CCM user interface (UI):
In the CCM UI left navigation panel, click Infrastructure → COMPUTE NODES → AMD SEV-SNP, and then click ADD NODE.
On the Enroll Compute Node dialog box, click DOWNLOAD ZONE CA. The downloaded certificate will be uploaded by the Publisher (Model Owner) to Fortanix DSM in Section 5.0: Configure Fortanix DSM.
(1).png?sv=2026-02-06&spr=https&st=2026-10-09T06%3A13%3A38Z&se=2026-10-09T06%3A52%3A38Z&sr=c&sp=r&sig=hcRYbyY%2Bfr8oaB3YRS1P0P8Q35LPHJB3E72e2lI%2B1AU%3D)
Figure 2: Download Zone CA
5.4 Create an Application in CCM
Perform the following steps to add an application:
In the CCM UI left navigation panel, click Applications.
On the ACTIVE APPLICATIONS tab, click ADD APPLICATION to add an application.
In the Add Application form,
Under Select application type, select Confidential Container - CoCo.
Under Select platform type, select AMD SEV-SNP.
Click NEXT.
In the Add Application Confidential Container - CoCo form:
Application name: Enter the name of the application.
Description (optional): Enter the application’s description.
Group: Select the required group from the drop down menu.
Certificate Configuration: Add certificates using ADD CERTIFICATE. An application can request a certificate from Fortanix CCM when the application starts. The certificates are signed by the Fortanix CCM Certificate Authority, which issues certificates only to trusted workloads presenting a valid attestation.
Domain: Enter the allowed domain for the application. This is the domain that appears in the TLS certificate issued by Fortanix CCM.
Type: Select the certificate type for the application from the drop down menu.
Click ADD APPLICATION to configure the application.
The application is added for approval and appears on the Applications page. You can approve the request from the Tasks page.
After the application is created, deploy the workload on a platform that supports AMD SEV-SNP and obtain the required attestation measurements. These values are used when creating the application build for the Confidential Container - CoCo application on AMD SEV-SNP in Fortanix CCM.
For detailed instructions on creating an AMD SEV-SNP application, refer to Add Coco - AMD SEV-SNP Application.
6.0 Configure Fortanix DSM
Configure Fortanix DSM to create the account, group, application, and security objects required to protect the container image encryption keys.
6.1 Create an Account and Group
A Fortanix DSM account is the top-level container for security objects managed by Fortanix DSM. An account is generally associated with an organization, rather than an individual. Security objects, groups, and applications belong to exactly one account. Different accounts are fully isolated from each other.
To get started with Fortanix DSM you must first sign up in and create an account. If you already have an existing account, log in to that account.
For more information on how to sign up and log in to Fortanix DSM account, refer to Sign Up for Fortanix Data Security Manager SaaS.
For more information on setting up an account and creating a group, refer to Getting Started with Fortanix Data Security Manager - UI.
6.2 Create an Application (app) with Trusted CA Authentication
Create an application to authenticate to Fortanix DSM using a Transport Layer Security (TLS) client certificate signed by a Trusted Certificate Authority (CA). This app will be used for decrypting the model and weights when the Confidential Virtual Machine (CVM) launches.
Click the Groups menu item from the DSM left navigation panel and select the group you created in Section 6.1: Create an Account and Group to go to its detailed view.
Click APPS → ADD APP to create a new application.

Figure 3: Create an app
Follow the steps here to configure a new app with the following details:
Interface: REST API
Authentication Method: Trusted CA
DNS Name: my-server
Upload Trusted CA Cert: Upload the Zone CA Certificate downloaded and shared by Consumer (Enterprise) in Section 5.3: Download Zone CA Certificate from your Fortanix CCM Account.
Click SAVE.

Figure 4: App with Trusted CA authentication
6.3 Create an App with API Key Authentication
Create an application to authenticate to Fortanix DSM using an API key. This API key is a random, secret token that identifies an app in the same way as a password identifies a user. This app will be used for encrypting the model and weights.
Repeat Steps 1-2 from previous Section 6.2: Create an Application (app) with Trusted CA Authentication.
Follow the steps here to configure a new app with the following details
Interface: REST API
Authentication Method: API Key
Click SAVE.

Figure 5: App with API key authentication
3. Click SAVE.
7.0 Prepare the Encrypted Container Image
The following sections describe the steps to encrypt the container image using the Fortanix CoCo Encryption Tool (coco-keyprovider Docker image) with keys managed by Fortanix DSM. The encrypted image is then published to a container registry so that it can be pulled by your Kubernetes cluster.
7.1 Containerize the Application
Create a container image for the application that will run in the Confidential Container environment.
For example, the following image can be used for testing
nginx:latestThe same procedure can be used with an application-specific container image.
7.2 Configure DSM Authentication for Image Encryption
Create a JSON configuration file containing the Fortanix DSM endpoint and API key for the DSM application used for container image encryption.
For example (JSON):
{
"api-endpoint": "<DSM_URL>",
"api-key": "<DSM_API_KEY>"
}Where,
<DSM_API_KEY>: The API key generated for the DSM application in Section 6.0: Configure Fortanix DSM.<DSM_URL>: The Fortanix DSM endpoint URL.DSM SaaS: Use the endpoint for your DSM region.
DSM on-premises: Use the configured DSM endpoint.
7.3 Encrypt the Container Image
Run the following command which pulls Fortanix CoCo Encryption Tool Docker image and encrypts the application container image. The tool publishes the encrypted image to the given output image registry:
docker run -v <path>/dsm-config.json:/dsm-config.json:ro \
-v ~/.docker/config.json:/root/.docker/config.json \
fortanix/coco-keyprovider:0.2.12 /dsm-encrypt.sh \
--fortanix-dsm-config /dsm-config.json \
--input-image docker://<DOCKER_REPO>:<DOCKER_TAG> \
--output-image docker://<DOCKER_REPO>:<DOCKER_TAG> \
--kek-name <KEK_NAME> \
--kek-mode sharedWhere,
--fortanix-dsm-config <file>: The DSM configuration file containing the API Key and the DSM endpoint.--input-image <ref>: The source container image and tag.--output-image <ref>: The destination for the encrypted container image and tag.
--socket <host:port>: The keyprovider gRPC socket. The default is127.0.0.1:50000.--keyid <uuid|kbs:///dsm/key/uuid>: Reuses an existing DSM KEK. By default, a new KEK is created. When--keyidis specified, one KEK is used for the whole image.--kek-name <name>: The DSM object name for the KEK or KEKs created. In per-layer mode, the layer index is appended to the name, such as<name>-0,<name>-1, and so on.--kek-mode <shared|per-layer>: The KEK configuration for the image.shareduses one KEK to wrap every encrypted layer, whileper-layercreates a separate KEK for each encrypted layer.--encrypt-layer <spec>: The layers to encrypt. Use all to encrypt every layer or specify comma-separated zero-based layer indexes. Negative indexes count from the end. For example:all: encrypts every layer0,1: encrypts the first two layers-1: encrypts the last layer only
--dest-tls-verify <true|false>: Specifies whether to verify TLS certificates for Docker destinations. The value is passed through to Skopeo.--ready-timeout <seconds>: The keyprovider startup wait time. The default is 30 seconds.-h,--help: Displays the command usage and available options.
The encryption tool generates or uses a KEK in DSM to protect the LEKs generated by Skopeo to encrypt the container image layers. You can verify the generated keys in the DSM UI.
NOTE
Only the encrypted container image is shared, you do not need to share the plaintext container image or protected application artifacts
8.0 Prepare the Confidential Computing Environment
You must prepare the confidential computing and Kubernetes environment before deploying the encrypted container. The environment consists of a confidential-computing host, a Kubernetes cluster, the Fortanix Node Agent, the NVIDIA GPU Operator, and Fortanix CoCo Helm Chart.
The following procedures must be completed on the host and Kubernetes environment.
8.1 Prepare the Confidential Computing Host
Ensure that the confidential-computing host meets the requirements described in Section 3.3: Confidential Computing Host Requirements and is configured according to the applicable AMD SEV-SNP host prerequisites.
8.2 Set Up the Kubernetes Cluster
Ensure that the Kubernetes environment meets the requirements described in Section 3.4: Kubernetes Requirements before proceeding with the following steps.
8.3 Enroll Node with CCM
The Fortanix Node Agent enables compute-node registration with Fortanix CCM and supports application attestation and workload visibility. It verifies the integrity of the underlying hardware and software running on the node. The Fortanix Node Agent runs on the host and provides the communication path between the CoCo Attestation Agent and Fortanix CCM.
For detailed instructions on how to download and install the Fortanix Node Agent on your confidential computing host and enroll a compute node with CCM, refer to Enroll a Compute Node Using Bare Metal - AMD SEV-SNP.
8.4 Install the NVIDIA GPU Operator
Install the NVIDIA GPU Operator on the Kubernetes cluster to enable NVIDIA GPU resources for the Confidential Containers workload as described in the following steps:
NOTE
Ensure that NVIDIA GPU drivers are not installed or loaded on the host before installing the NVIDIA GPU Operator
Run the following command to label the Kubernetes node for GPU passthrough:
kubectl label node <NODE_NAME> \ nvidia.com/gpu.workload.config=vm-passthroughRun the following commands to add the NVIDIA Helm repository, which provides the NVIDIA GPU Operator Helm chart:
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia helm repo updateRun the following command to install the NVIDIA GPU Operator:
helm install --generate-name \ -n gpu-operator --create-namespace \ nvidia/gpu-operator \ --set sandboxWorkloads.enabled=true \ --set sandboxWorkloads.mode=kata \ --set nfd.enabled=true \ --set nfd.nodefeaturerules=true \ --version=v26.3.1Enable the
KubeletPodResourcesGetandRuntimeClassInImageCriApifeature gates in the Kubernetes cluster:Open the
Kubeletconfiguration file, for example:sudo vi /var/lib/kubelet/config.yamlAdd the following configuration to the file:
volumeStatsAggPeriod: 0s featureGates: KubeletPodResourcesGet: true RuntimeClassInImageCriApi: trueRun the following command to restart the Kubelet service:
sudo systemctl restart kubelet
Run the following command to verify that the NVIDIA GPU Operator pods are running:
kubectl get pods -n gpu-operatorVerify that the required GPU Operator pods are in the Running state. Pod names and restart counts may vary.
Example output:
NAME READY STATUS RESTARTS AGE gpu-operator-1783520009-node-feature-discovery-gc-66d748c4dtvbb 1/1 Running 1 (100s ago) 15m gpu-operator-1783520009-node-feature-discovery-master-58cckrzql 1/1 Running 1 (100s ago) 15m gpu-operator-1783520009-node-feature-discovery-worker-xpcxg 1/1 Running 1 (100s ago) 15m gpu-operator-67866486c9-j8t8p 1/1 Running 1 (100s ago) 15m nvidia-cc-manager-54vwm 1/1 Running 1 (100s ago) 15m nvidia-kata-sandbox-device-plugin-daemonset-7zvqh 1/1 Running 1 (100s ago) 15m nvidia-sandbox-validator-kdrdf 1/1 Running 0 66s nvidia-vfio-manager-schl8 1/1 Running 0 15mNOTE
The
nvidia-vfio-manager-*pods do not start if the NVIDIA driver (nvidia-driver) is already installed on the host. Follow the steps in Removing the Driver - NVIDIA Driver Installation Guide to remove the driver. A system reboot is required after removing the driver.
8.5 Install Fortanix CoCo Helm Chart
Install the Fortanix CoCo Helm Chart on the Kubernetes cluster. Helm chart installs the Fortanix-specific Confidential Containers runtime, including the runtime configurations required for AMD SEV-SNP workloads.
Perform the following steps:
Run the following command to install the Fortanix CoCo Helm chart:
helm install coco \ oci://ghcr.io/confidential-containers/charts/confidential-containers \ --version 0.21.0 \ --namespace coco-system \ --create-namespace \ --set kata-as-coco-runtime.image.reference=<IMAGE_REFERENCE> \ --set kata-as-coco-runtime.image.tag=<IMAGE_TAG>Where,
<IMAGE_REFERENCE>: The image reference for the Beta release isfortanix/kata-deploy.<IMAGE_TAG>: The image tag for the Beta release is0.21.0-fortanix-ccm-0.2.12.
Run the following command to verify that the Fortanix CoCo DaemonSet is successfully deployed:
kubectl -n coco-system rollout status ds/kata-as-coco-runtimeThe command should report that the DaemonSet rollout has completed successfully.
Expected output:
The command should report that the DaemonSet rollout has completed successfullyRun the following command to verify the Fortanix CoCo logs:
kubectl -n coco-system logs \ -l name=kata-as-coco-runtime \ --tail=50Verify that the logs indicate that the required runtimes were configured successfully and the node became ready.
Example output:
[2026-09-16T05:50:49Z INFO kata_deploy::runtime::containerd] Configuring runtime for shim: qemu-nvidia-gpu-snp-runtime-rs [2026-09-16T05:50:49Z INFO kata_deploy::runtime::containerd] configure_containerd_runtime: Writing to "/host/opt/kata/containerd/config.d/kata-deploy.toml", pluginid="io.containerd.cri.v1.runtime" [2026-09-16T05:50:49Z INFO kata_deploy::runtime::containerd] Successfully configured runtime for shim: qemu-nvidia-gpu-snp-runtime-rs [2026-09-16T05:50:49Z INFO kata_deploy::runtime::containerd] Configuring runtime for shim: qemu-snp [2026-09-16T05:50:49Z INFO kata_deploy::runtime::containerd] configure_containerd_runtime: Starting for shim=qemu-snp [2026-09-16T05:50:49Z INFO kata_deploy::runtime::containerd] configure_containerd_runtime: Writing to "/host/opt/kata/containerd/config.d/kata-deploy.toml", pluginid="io.containerd.cri.v1.runtime" [2026-09-16T05:50:49Z INFO kata_deploy::runtime::containerd] Successfully configured runtime for shim: qemu-snp [2026-09-16T05:50:49Z INFO kata_deploy::runtime::containerd] Configuring runtime for shim: qemu-sev[2026-09-16T05:50:49Z INFO kata_deploy::runtime::containerd] configure_containerd_runtime: Starting for shim=qemu-snp [2026-09-16T05:50:49Z INFO kata_deploy::runtime::containerd] configure_containerd_runtime: Writing to "/host/opt/kata/containerd/config.d/kata-deploy.toml", pluginid="io.containerd.cri.v1.runtime" [2026-09-16T05:50:49Z INFO kata_deploy::runtime::containerd] Successfully configured all containerd runtimes [2026-09-16T05:50:49Z INFO kata_deploy::artifacts::snapshotters] Deploying nydus-for-kata-tee [2026-09-16T05:50:50Z INFO kata_deploy::artifacts::snapshotters] Configuring nydus-for-kata-tee [2026-09-16T05:50:50Z INFO kata_deploy] About to restart runtime: containerd [2026-09-16T05:50:50Z INFO kata_deploy::runtime::lifecycle] restart_runtime: Starting restart for runtime=containerd [2026-09-16T05:50:50Z INFO kata_deploy::runtime::lifecycle] restart_runtime: Running daemon-reload [2026-09-16T05:50:51Z INFO kata_deploy::runtime::lifecycle] restart_runtime: Restarting containerd service [2026-09-16T05:50:51Z INFO kata_deploy::runtime::lifecycle] restart_runtime: Successfully restarted containerd service [2026-09-16T05:50:51Z INFO kata_deploy::runtime::lifecycle] restart_runtime: Waiting for node to become ready [2026-09-16T05:50:51Z INFO kata_deploy::runtime::lifecycle] wait_till_node_is_ready: Node try-72165-gpu01 ready status = 'True' (attempt 1) [2026-09-16T05:50:51Z INFO kata_deploy::runtime::lifecycle] Node try-72165-gpu01 is ready [2026-09-16T05:50:51Z INFO kata_deploy::runtime::lifecycle] restart_runtime: Node is ready [2026-09-16T05:50:51Z INFO kata_deploy] Runtime restart completed successfully [2026-09-16T05:50:51Z INFO kata_deploy::k8s::client] Setting label katacontainers.io/kata-runtime=true on node try-72165-gpu01 [2026-09-16T05:50:51Z INFO kata_deploy] Kata Containers installation completed successfully [2026-09-16T05:50:51Z INFO kata_deploy] Install completed, re-exec'ing into post-install waiter [2026-09-16T05:50:51Z INFO kata_deploy::config] Action: [2026-09-16T05:50:51Z INFO kata_deploy::config] * internal-post-install-wait [2026-09-16T05:50:51Z INFO kata_deploy::config] [2026-09-16T05:50:51Z INFO kata_deploy::config] Environment variables passed to this script [2026-09-16T05:50:51Z INFO kata_deploy::config] * NODE_NAME: try-72165-gpu01 [2026-09-16T05:50:51Z INFO kata_deploy::config] * DEBUG: false [2026-09-16T05:50:51Z INFO kata_deploy::config] * SHIMS: clh-runtime-rs qemu-coco-dev qemu-coco-dev-runtime-rs qemu-nvidia-gpu-runtime-rs qemu-nvidia-gpu-snp qemu-nvidia-gpu-snp-runtime-rs qemu-snp [2026-09-16T05:50:51Z INFO kata_deploy::config] * DEFAULT_SHIM: qemu-snp [2026-09-16T05:50:51Z INFO kata_deploy::config] * ALLOWED_HYPERVISOR_ANNOTATIONS: [2026-09-16T05:50:51Z INFO kata_deploy::config] * SNAPSHOTTER_HANDLER_MAPPING: Some("qemu-coco-dev:nydus,qemu-coco-dev-runtime-rs:nydus,qemu-nvidia-gpu-snp:nydus,qemu-nvidia-gpu-snp-runtime-rs:nydus,qemu-nvidia-gpu-snp:nydus,qemu-snp:nydus") [2026-09-16T05:50:51Z INFO kata_deploy::config] * AGENT_HTTPS_PROXY: None [2026-09-16T05:50:51Z INFO kata_deploy::config] * AGENT_NO_PROXY: None [2026-09-16T05:50:51Z INFO kata_deploy::config] * PULL_TYPE_MAPPING: Some("qemu-coco-dev:guest-pull,qemu-coco-dev-runtime-rs:guest-pull,qemu-nvidia-gpu-snp:guest-pull,qemu-nvidia-gpu-snp-runtime-rs:guest-pull,qemu-nvidia-gpu-snp:guest-pull,qemu-snp:guest-pull") [2026-09-16T05:50:51Z INFO kata_deploy::config] * INSTALLATION_PREFIX: None [2026-09-16T05:50:51Z INFO kata_deploy::config] * MULTI_INSTALL_SUFFIX: None [2026-09-16T05:50:51Z INFO kata_deploy::config] * HELM_POST_DELETE_HOOK: false [2026-09-16T05:50:51Z INFO kata_deploy::config] * EXPERIMENTAL_SETUP_SNAPSHOTTER: Some(["nydus"]) [2026-09-16T05:50:51Z INFO kata_deploy::config] * EXPERIMENTAL_FORCE_GUEST_PULL: qemu-nvidia-gpu-snp [2026-09-16T05:50:51Z INFO kata_deploy::config] * CONTAINERD_CONF_FILE: /etc/containerd/config.toml [2026-09-16T05:50:51Z INFO kata_deploy::config] * CUSTOM_RUNTIMES_ENABLED: false [2026-09-16T05:50:51Z INFO kata_deploy::health] Health server resumed from inherited fd=9 [2026-09-16T05:50:51Z INFO kata_deploy] Post-install waiter ready, blocking on SIGTERMRun the following command to verify that the Helm release is deployed:
helm list -n coco-systemExpected output:
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION coco coco-system 1 <timestamp> deployed confidential-containers-0.21.0 0.21.0
9.0 Register Application Measurements with CCM
You must register the application measurements in Fortanix CCM before deploying the workload to enable CCM to verify that the Confidential Container is running in the expected trusted environment.
9.1 Create the InitData Configuration
Create an initdata.toml file containing the configuration required by the Confidential Containers runtime to communicate with Fortanix CCM and DSM.
Configure ccm_as to communicate with CCM and ccm_kbc to communicate with DSM for the required key operation.
For example:
version = "0.1.0"
algorithm = "sha384"
[data]
"aa.toml" = '''
[token_configs.ccm_as]
ccm_domain_names = ["fortanix.com"]
'''
"cdh.toml" = '''
[kbc]
name = "ccm_kbc"
url = "https://apps.dsm.example.com"
[kbc_configs.ccm_kbc]
dsm_app_id = "<DSM_TRUSTED_CA_APP_UUID>"
'''Where,
ccm_domain_names: The DNS identities to be included in the CCM-issued application certificate. The domain name(s) must match the DNS name configured for the DSM application when using Trusted CA authentication as described in Section 6.2: Create an Application with Trusted CA Authentication.NOTE
You can specify multiple domain names by providing a comma-separated list of domains. For example:
ccm_domain_names = ["fortanix.com", "fortanix.net"]url: The DSM endpoint.dsm_app_id: The UUID of the DSM application created in Section 6.2: Create an Application with Trusted CA Authentication configured for Trusted CA authentication.
NOTE
Replace the example CCM domain, DSM endpoint, and DSM application UUID with the values provided for your environment.
9.2 Encode the InitData
Run the following command to compress the
initdata.tomlfile using gzip and encode the result using Base64:initdata=$(cat initdata.toml | gzip | base64 -w0)Note the resulting Base64-encoded value. Use this value in the Kubernetes workload configuration for the annotation:
io.katacontainers.config.hypervisor.cc_init_datain Section 9.3: Obtain Application Measurements.
9.3 Obtain Application Measurements
To calculate the measurements, perform the following steps.
Create a sample pod YAML file on the host to obtain the application measurements.
For an AMD SEV-SNP workload, use the following configuration:
apiVersion: v1 kind: Pod metadata: name: <MEASUREMENT_POD> annotations: io.containerd.cri.runtime-handler: kata-qemu-nvidia-gpu-snp io.katacontainers.config.hypervisor.kernel_params: "agent.guest_components_rest_api=all" io.katacontainers.config.hypervisor.cc_init_data: "<BASE64_ENCODED_INITDATA>" spec: runtimeClassName: kata-qemu-nvidia-gpu-snp restartPolicy: Never containers: - name: sample-os-container image: ubuntu:22.04 resources: limits: nvidia.com/pgpu: "1" memory: 16Gi securityContext: privileged: true ports: - containerPort: 80Where,
<MEASUREMENT_POD>: The container image used to generate the attestation measurements<BASE64_ENCODED_INITDATA>: The base64 encodedinitdata.tomlcontent generated in Section 9.2: Encode the InitData. required by the Confidential Containers runtime to communicate with Fortanix CCM and DSM.
NOTE
For non-GPU workloads, remove the
resourcessection from the pod configuration.The sample measurement workload requires privileged access for the validation procedure. Do not use this configuration for production workloads unless privileged access is required by the application.
Run the following command to deploy the sample measurement workload:
kubectl apply -f measurements.yamlRun the following command to verify that the pod is running:
kubectl get podsFor example:
NAME READY STATUS RESTARTS AGE <MEASUREMENT_POD> 1/1 Running 0 1mReplace
<MEASUREMENT_POD>with the name of the measurement pod.Run the following command to obtain the attestation evidence from the running pod for AMD SEV-SNP:
kubectl exec <MEASUREMENT_POD> -- bash -c " apt-get update -qq && apt-get install -qq -y curl python3 >/dev/null "Then run the following command to generate the measurements:
kubectl exec <MEASUREMENT_POD> -- bash -c "curl -s 'http://127.0.0.1:8006/aa/evidence?runtime_data=dGVzdA==' | python3 -c ' import sys, json d = json.load(sys.stdin) r = d[\"attestation_report\"] print(\"measurement:\", bytes(r[\"measurement\"]).hex()) print(\"host_data: \", bytes(r[\"host_data\"]).hex()) '"The output displays the
measurementandhost_datavalues. For example:measurement: b71ad03793de8c0cc4bca04c00ddc7b441c03bc1548b94a880b33f1b8af22fb846c11ff9f492817c4a2b7178396888fb host_data: 695462b3eb927997e7a704a6df90f1abf174ef4efc5a1f4e20a07c6684cae001
9.4 Register the Measurements in CCM
Perform the following steps to register the measurements in CCM:
In the Fortanix CCM UI, open the application created in Section 5.4: Create an Application in CCM.
On the following page, click ADD BUILD to configure the build of the AMD SEV-SNP application.
In the Add Build form:
Build Version: Enter a unique tag for the build.
In the Secure VM attestation section,
Measurement: Enter the platform-specific attestation measurement value generated in Section 9.3: Obtain Application Measurements to register the required SEV-SNP measurement information.
HOST_DATA: Enter the hash of the InitData configuration generated in Section 9.3: Obtain Application Measurements. CoCo embeds this hash in the
HOST_DATAfield at pod launch. CCM uses the registered hash to verify the integrity of the InitData configuration during the attestation flowVMPL: Select the VMPL0, VMPL1, VMPL2, or VMPL3 as Virtual Machine Privilege Level.
Coprocessors: Select an option to configure the NVIDIA Graphics Processing Unit (GPU) attestation setting:
Ignored: The virtual machine (VM) must have a GPU, and the attestation agent collects GPU attestation data, but Fortanix CCM does not validate this attestation, it only checks that GPU attestation data is present. The actual attestation result is ignored during verification.
Required: The VM must have a GPU, and the attestation agent collects GPU attestation data, and Fortanix CCM validates this data using NVIDIA Remote Attestation Service (NRAS).
Click ADD BUILD to create the build.
A build approval task is created and added, which is visible on the Tasks page. You can approve the task to approve the build.
For more information on how to approve the application build tasks for the CoCo AMD SEV-SNP application, refer to Domain and Application Build Approval.
After the build is approved, a green tick will appear in the Approval status column for that build.
.png?sv=2026-02-06&spr=https&st=2026-10-09T06%3A13%3A38Z&se=2026-10-09T06%3A52%3A38Z&sr=c&sp=r&sig=hcRYbyY%2Bfr8oaB3YRS1P0P8Q35LPHJB3E72e2lI%2B1AU%3D)
Figure 6: Create Build - CoCo AMD SEV-SNP
10.0 Deploy the Confidential Container
After preparing the environment registering the application measurements with CCM, deploy the encrypted container image as a Confidential Container.
The workload is deployed through Kubernetes using the Kata runtime. The Kata deployment on the host provides the confidential VM image, kernel, and runtime configuration required to run the workload in a TEE environment
The workload configuration specifies the encrypted container image, the Confidential Containers runtime, and the configuration required for attestation and secure key release.
When the workload starts, the CoCo runtime launches the workload in a TEE. Inside the TEE, the kata-agent manages the Kubernetes pod lifecycle, while image-rs retrieves the encrypted container image from the container registry. The ccm_kbc module uses the CCM-issued certificate to authenticate to Fortanix DSM using mTLS (mutual TLS). After successful attestation, DSM authorizes the workload and performs the LEK unwrapping operation using the non-exportable KEK, while keeping the key protected in DSM. After the LEK is unwrapped, image-rs, with the help of ocicrypt-rs, decrypts the encrypted image layers using the unwrapped LEK.
10.1 Create the Kubernetes Workload
Create a Kubernetes YAML file for the encrypted container.
For an AMD SEV-SNP workload, specify the following:
runtimeClassName: kata-qemu-nvidia-gpu-snpruntimeClassName: kata-qemu-snpEnter the Base64-encoded InitData using the following annotation:
io.katacontainers.config.hypervisor.cc_init_data: "<BASE64_ENCODED_INITDATA>"The required CoCo guest and Fortanix configuration can be provided either through InitData or kernel parameters.
Use the following kernel parameters:
io.katacontainers.config.hypervisor.kernel_params: agent.guest_components_rest_api=all agent.aa_kbc_params=ccm_kbc::default ccm.kbc_dsm_endpoint=https://apps.amer.smartkey.io"Where:
agent.guest_components_procs: Enables the required CoCo guest processes.agent.guest_components_rest_api: Enables the guest component REST API.agent.aa_kbc_params: Configures theccm_kbcKey Broker Client.ccm.kbc_dsm_endpoint: Specifies the Fortanix DSM endpoint used for secure key release.
NOTE
Using InitData is the recommended approach. Do not configure the same parameters in both locations.
Enter the encrypted container image that you published:
image: <REGISTRY>/<REPOSITORY>:<TAG>If the workload requires an NVIDIA GPU, specify the GPU resource:
NOTE
The Confidential Container workload configuration must match the configuration used to obtain the application measurements, including the runtime configuration and InitData. Changes to the measured configuration can result in an attestation measurement mismatch and prevent the workload from being attested by CCM
resources: limits: nvidia.com/pgpu: "1"Example Kubernetes Workload YAML file (
workload-gpu.yaml):apiVersion: v1 kind: Pod metadata: name: <WORKLOAD_NAME> annotations: io.containerd.cri.runtime-handler: kata-qemu-nvidia-gpu-snp io.katacontainers.config.hypervisor.kernel_params: "agent.guest_components_rest_api=all" io.katacontainers.config.hypervisor.cc_init_data: "<BASE64_ENCODED_INITDATA>" io.containerd.cri.runtime-handler: kata-qemu-nvidia-gpu-snp spec: runtimeClassName: kata-qemu-nvidia-gpu-snp restartPolicy: Never containers: - name: <CONTAINER_NAME> image: <REGISTRY>/<REPOSITORY>:<TAG> resources: limits: nvidia.com/pgpu: "1" memory: 16Gi securityContext: privileged: true ports: - containerPort: 80
10.2 Deploy the Workload
Run the following command to apply the workload configuration:
kubectl apply -f workload-gpu.yamlRun the following command to verify the workload:
kubectl get podsAfter the workload starts, image-rs, with the help of ocicrypt-rs, decrypts the encrypted container image layers using the unwrapped LEK. The application or model can then run inside the confidential environment.
11.0 Verify the Confidential Container
When the workload starts, the CoCo Attestation Agent uses the ccm_as module to collect TEE attestation evidence and obtain an application certificate from Fortanix CCM. The ccm_kbc module uses the certificate to authenticate to Fortanix DSM through Trusted CA Authentication and perform the required key operation. Verify the attestation and key-operation flow using the CCM application certificate, application deployment state, and DSM audit logs.
Perform the following verification steps:
11.1 Verify the DSM Audit Logs
In Fortanix DSM, open the application configured for Trusted CA Authentication. Verify that the application activity logs contain audit entries corresponding to the key operations performed by the attested workload.
.png?sv=2026-02-06&spr=https&st=2026-10-09T06%3A13%3A38Z&se=2026-10-09T06%3A52%3A38Z&sr=c&sp=r&sig=hcRYbyY%2Bfr8oaB3YRS1P0P8Q35LPHJB3E72e2lI%2B1AU%3D)
Figure 7: DSM app audit logs
11.2 Verify the Application Certificate in CCM
In Fortanix CCM, open the AMD SEV-SNP application and select the CERTIFICATE tab. Verify that the certificate issued to the successfully attested workload is displayed. The certificate details include the certificate domain, issuer, validity period, and public key information.

Figure 8: Application Certificate
11.3 Verify the Application Deployment
In Fortanix CCM, open the AMD SEV-SNP application and select the BUILDS tab. Verify that the application build shows the deployment state as Deployed.
.png?sv=2026-02-06&spr=https&st=2026-10-09T06%3A13%3A38Z&se=2026-10-09T06%3A52%3A38Z&sr=c&sp=r&sig=hcRYbyY%2Bfr8oaB3YRS1P0P8Q35LPHJB3E72e2lI%2B1AU%3D)
Figure 9: Application Build Deployed
12.0 Troubleshooting
This section describes common issues that may occur during the deployment and execution of Confidential Containers (CoCo) and provides recommended resolutions for each issue.
PROBLEM | RESOLUTION |
|---|---|
| Add the following annotation to the |
| The |
| Remove the |
| This is caused by a CDI version mismatch with NVIDIA Container Toolkit 1.20.0. If you do not want to downgrade to version 1.19.x, delete |
| Recreate the CCM application build with valid measurements. |
| Verify that the measurements registered in CCM match the measurement workload configuration. The measurement YAML and workload YAML must contain the same relevant fields, particularly GPU configuration and annotations. To avoid measurement mismatch:
|
| The CCM build was configured with GPU coprocessor attestation set to Required for a non-GPU workload. Recreate the CCM build with NVIDIA GPU attestation set to Ignored. |
Node Agent reports | The underlying |
|
|
| IOMMU in passthrough · Issue #88 · AMDESE/AMDSEV 1. Remove 2. Run |
| Update the kernel on the host. |
| The microcode is out of date. Contact the server vendor for a BIOS update that includes the latest microcode and update the BIOS. |
Workload is not scheduled on the node. | Verify the following:
|
| Increase the memory allocated to the workload in the workload YAML. For example: Increase the memory value as needed and restart the workload. |
|
|