This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Installation

Installing Trustee

Trustee can be deployed in several different configurations. In every installation scenario, deploy Trustee in a trusted environment. This could be a local server, some trusted third party, or even another enclave. Official support for deploying Trustee inside of Confidential Containers is being developed.

Choosing an installation method

Method Best for
Helm Development or production deployments, where you want declarative configuration or advanced options (custom storage, BYOK, IBM SE)
Trustee Operator Kubernetes deployments with operator-managed lifecycle
Docker Compose Local evaluation, development, and testing

1 - Trustee with Helm

Installing Trustee on Kubernetes with Helm

Use the Helm chart to deploy Trustee on Kubernetes with declarative control over the deployment. The chart deploys KBS, the gRPC Attestation Service (AS), and RVPS. It can also deploy PostgreSQL through the Bitnami chart. KBS connects to the remote coco_as_grpc Attestation Service.

Prerequisites

  • Kubernetes 1.19 or later
  • Helm 3
  • A usable StorageClass or an existing bound claim for PostgreSQL storage (storageBackend.type: Postgres or sessionStorageType: Postgres). The Bitnami subchart uses persistent volume claim (PVC)-backed storage.

Install

  1. Clone the repository:

    git clone https://github.com/confidential-containers/trustee.git
    
  2. Navigate into the repository:

    cd trustee
    
  3. Update the Helm chart:

    helm dependency update ./deployment/helm-chart
    
  4. Deploy the Helm chart:

    helm upgrade --install trustee ./deployment/helm-chart \
      --namespace coco-trustee --create-namespace
    

    Expected output:

    Release "trustee" does not exist. Installing it now.
    NAME: trustee
    LAST DEPLOYED: Sat Jul 18 02:47:16 2026
    NAMESPACE: coco-trustee
    STATUS: deployed
    REVISION: 1
    DESCRIPTION: Install complete
    TEST SUITE: None
    
  5. Check the status of the deployment:

    kubectl get pods -n coco-trustee -w
    

    Expected output:

    NAME                           READY   STATUS     RESTARTS   AGE
    trustee-as-74b4c898d8-rkdvk    1/1     Running    0          19s
    trustee-kbs-d7cb6d957-7ct47    1/1     Running    0          19s
    trustee-rvps-7d6c58d8f-mknqd   1/1     Running    0          19s
    

    Wait for all workloads to reach the Running state before continuing.

  6. Forward local port 8080 to the KBS service. The internal ClusterIP service is named <Helm fullname>-kbs. For this installation, the name is trustee-kbs.

    kubectl port-forward -n coco-trustee svc/trustee-kbs 8080:8080
    

Refer to the validate the deployment section for details on checking your Trustee instance after installation.

Helm configuration options

The default values.yaml contains only the required settings for deploying Trustee. For all available options, see the Helm chart values documentation.

Deployment scenarios

The following sections show common Trustee deployment scenarios.

LocalFs storage (default)

If neither storageBackend.type nor sessionStorageType is set to Postgres, the chart does not deploy the bundled PostgreSQL database. Components instead use the default storageBackend, such as LocalFs, on your cluster.

helm dependency update ./deployment/helm-chart

helm upgrade --install trustee ./deployment/helm-chart \
  --namespace coco-trustee --create-namespace

PostgreSQL storage with in-memory KBS sessions

helm dependency update ./deployment/helm-chart

helm upgrade --install trustee ./deployment/helm-chart \
  --namespace coco-trustee --create-namespace \
  -f ./deployment/helm-chart/scenarios/postgres-backend.yaml

This configuration enables the Bitnami PostgreSQL subchart (postgresql.enabled: true) and sets storageBackend.type: Postgres. KBS sessions remain in memory (sessionStorageType: Memory). The default demo database name, username, and password are all trustee. Override them with postgresql.auth.*.

External PostgreSQL

To use an external PostgreSQL service, set storageBackend.postgres.mode=external, create a Secret containing a POSTGRES_URL key, and configure the chart to use it:

kubectl create secret generic trustee-external-postgres -n coco-trustee \
  --from-literal=POSTGRES_URL='postgresql://user:password@postgres.example.com:5432/trustee?sslmode=require'

helm upgrade --install trustee ./deployment/helm-chart \
  --namespace coco-trustee --create-namespace \
  --set storageBackend.type=Postgres \
  --set storageBackend.postgres.mode=external \
  --set storageBackend.postgres.external.existingSecretName=trustee-external-postgres \
  --set storageBackend.postgres.external.existingSecretKey=POSTGRES_URL

When storageBackend.postgres.mode=external, the chart does not deploy the Bitnami subchart (postgresql.enabled remains false), even when storageBackend.type or sessionStorageType requires PostgreSQL.

Bring your own keys (BYOK)

The secrets.useEphemeralGeneratedKeys setting controls key material:

  • true (default): A Helm pre-install and pre-upgrade hook Job generates ephemeral demo keys in a release-scoped Secret whose name ends with bootstrap-user-keys. A post-delete hook removes the Secret when you run helm uninstall.
  • false: Create a Kubernetes Secret in the target namespace and set secrets.existingSecretName to its name. The chart does not render the bootstrap hook.

When ephemeral generation is enabled, the hook uses:

  • An initContainer that uses an OpenSSL image to generate keys in an emptyDir.
  • A quay.io/kata-containers/kubectl container that creates the Secret from the generated files.

You can override both images with bootstrapUserKeysJob.keygenImage.* and bootstrapUserKeysJob.kubectlImage.*.

When ephemeral key generation is disabled, the Secret must define the following data keys. As with any kubectl create secret generic --from-file=... command, values are PEM text or base64-encoded PEM:

Secret key Role
KBS_ADMIN_PRIVATE_KEY / KBS_ADMIN_PUBKEY KBS admin API Ed25519 key pair used to sign admin JWTs
KBS_ADMIN_TOKEN Pre-signed admin bearer JWT for kbs-client --admin-token-file; the bootstrap hook generates it when ephemeral keys are enabled
AS_TOKEN_SIGNING_PRIVATE_KEY Private key that the Attestation Service uses to sign attestation tokens
AS_TOKEN_VERIFICATION_PUBLIC_KEY_CERT_CHAIN AS x5c certificate chain and KBS trust anchor for token verification

The chart mounts the Secret in KBS and gRPC AS. It maps the keys to the in-container paths private.key, public.pub, token.key, and token-cert-chain.pem under /opt/confidential-containers/kbs/user-keys.

Create the Secret, and then install Trustee:

kubectl create secret generic trustee-byok-keys -n coco-trustee \
  --from-file=KBS_ADMIN_PRIVATE_KEY=./admin.key.pem \
  --from-file=KBS_ADMIN_PUBKEY=./admin.pub.pem \
  --from-file=AS_TOKEN_SIGNING_PRIVATE_KEY=./token.key.pem \
  --from-file=AS_TOKEN_VERIFICATION_PUBLIC_KEY_CERT_CHAIN=./token-chain.pem

helm upgrade --install trustee ./deployment/helm-chart \
  --namespace coco-trustee --create-namespace \
  --set secrets.useEphemeralGeneratedKeys=false \
  --set secrets.existingSecretName=trustee-byok-keys

Alternatively, use scenarios/bring-your-own-keys.yaml and adjust the Secret name and file paths described in its comments.

IBM Secure Execution (s390x)

On s390x, the IBM Secure Execution (SE) verifier requires attestation materials at runtime. Because KBS connects to a remote coco_as_grpc AS, the verifier runs in the AS Pod. Mount these materials on AS, not KBS. This differs from the built-in AS Kustomize overlay in kbs/config/kubernetes/overlays/ibm-se, which mounts them on KBS.

The verifier reads materials from fixed paths under /run/confidential-containers/ibmse/. You can override these paths with SE_* environment variables; refer to deps/verifier/src/se/README.md. The chart mounts the materials from a local node path through a persistent volume (PV) and persistent volume claim (PVC):

  • Set as.verifier.se.credsDir to the directory on the node that contains the materials. This is equivalent to IBM_SE_CREDS_DIR in the Kustomize overlay.
  • Set as.verifier.se.nodeName to the name of that node.

The chart creates a local PV and PVC, and then mounts the directory at /run/confidential-containers/ibmse/ on the AS Pod.

Material Expected path under credsDir Notes
RSA measurement key pair rsa/encrypt_key.{pem,pub} The private key is sensitive; restrict node access
Signing and intermediate certificates certs/ Directory; all files are read
Certificate revocation lists (CRLs) crls/ Directory; all files are read
Host Key Documents (HKDs) hkds/ Directory; all files are read
SE image header hdr/hdr.bin Binary file
Root CA (optional) root_ca.crt Single file

Set CERTS_OFFLINE_VERIFICATION=true through as.extraEnvVars to verify the HKD certificate chain offline. Do not set SE_SKIP_CERTS_VERIFICATION=true outside a development environment because it disables HKD certificate chain verification.

# 1. Place all materials under a directory on the target s390x node, for example:
#    $IBM_SE_CREDS_DIR/{rsa/,certs/,crls/,hkds/,hdr/hdr.bin}
#    See deps/verifier/src/se/README.md for how to obtain the materials.

# 2. Install, pointing the chart at the node and directory:
helm upgrade --install trustee ./deployment/helm-chart \
  --namespace coco-trustee --create-namespace \
  -f ./deployment/helm-chart/scenarios/ibm-se.yaml \
  --set as.verifier.se.credsDir=$IBM_SE_CREDS_DIR \
  --set as.verifier.se.nodeName=<your-s390x-node-name>

Use an s390x AS image built with the se-verifier feature. Configure the image with as.image.repository and as.image.tag; see scenarios/ibm-se.yaml for the complete override. After installation, set the SE attestation policy as described in deps/verifier/src/se/README.md.

Validate the deployment

Inspect the deployed resources:

kubectl get deploy,pods,svc -n coco-trustee
helm status trustee -n coco-trustee

Render the chart without installing it:

helm dependency update ./deployment/helm-chart

helm template trustee ./deployment/helm-chart \
  -f ./deployment/helm-chart/scenarios/postgres-backend.yaml \
  --namespace coco-trustee > /tmp/trustee-render.yaml

Test KBS with kbs-client:

Build the client from the repository with cargo build -p kbs-client --release. When ephemeral keys are enabled, the hook-created Secret whose name ends with bootstrap-user-keys includes a pre-signed admin JWT under KBS_ADMIN_TOKEN. KBS expects authorization_mode = "AuthenticatedAuthorization" and a bearer JWT with a role claim that matches [admin.authorization.regex_acl]. The default role is admin.

kubectl port-forward -n coco-trustee svc/trustee-kbs 8080:8080 &
SECRET=$(kubectl get secrets -n coco-trustee -o name | grep bootstrap-user-keys | head -1 | cut -d/ -f2)
kubectl get secret "$SECRET" -n coco-trustee -o jsonpath='{.data.KBS_ADMIN_TOKEN}' | base64 -d >/tmp/admin-token
kbs-client --url http://127.0.0.1:8080 config --admin-token-file /tmp/admin-token set-resource-policy --allow-all

Set a confidential resource by configuring the admin token and then running set-resource:

echo 'demo-payload' >/tmp/demo-resource.txt
kbs-client --url http://127.0.0.1:8080 config --admin-token-file /tmp/admin-token set-resource \
  --path my_repo/resource_type/demo --resource-file /tmp/demo-resource.txt

Fetch the resource by its KBS URI path. get-resource is a top-level subcommand that uses the standard attestation and token flow for your client build and policy:

kbs-client --url http://127.0.0.1:8080 get-resource --path my_repo/resource_type/demo

Uninstall

Remove the release:

helm uninstall trustee -n coco-trustee

2 - Trustee Operator

Installing Trustee on Kubernetes

Use the Trustee Operator if you are running Kubernetes and want a managed installation that follows the Kubernetes operator pattern. The operator handles the Trustee lifecycle (install, upgrade, configuration) through a custom resource, making it a good fit for teams already using operators in their cluster. The entire Kubernetes cluster must be trusted.

Install the operator

The operator (release v0.17.0 at the time of writing) is available in the Operator Hub.

Please follow the installation steps detailed here.

Verify that the controller is running.

kubectl get pods -n operators --watch

The operator controller should be running.

NAME                                                   READY   STATUS    RESTARTS   AGE
trustee-operator-controller-manager-77cb448dc-7vxck    1/1     Running   0          11m

How to override the Trustee image

First of all we need to know which Trustee image is running:

kubectl get csv -n operators trustee-operator.v0.17.0 -o json | jq '.spec.install.spec.deployments[0].spec.template.spec.containers[0].env[1].value'
"ghcr.io/confidential-containers/key-broker-service:built-in-as-v0.16.0"

The default image can be replaced with an updated version, for example Trustee v0.17.0:

NEW_IMAGE=ghcr.io/confidential-containers/key-broker-service:built-in-as-v0.17.0
kubectl patch csv -n operators trustee-operator.v0.17.0 --type='json' -p="[{'op': 'replace', 'path': '/spec/install/spec/deployments/0/spec/template/spec/containers/0/env/1/value', 'value':$NEW_IMAGE}]"

Deploy Trustee

An example on how to configure Trustee is provided in this blog.

After the last configuration step, check that the Trustee deployment is running.

kubectl get pods -n operators --selector=app=kbs

The Trustee deployment should be running.

NAME                                  READY   STATUS    RESTARTS   AGE
trustee-deployment-f97fb74d6-w5qsm    1/1     Running   0          25m

Uninstall

Remove the Trustee CRD.

CR_NAME=$(kubectl get kbsconfig -n operators -o=jsonpath='{.items[0].metadata.name}') && kubectl delete KbsConfig $CR_NAME -n operators

Remove the controller.

kubectl delete Subscription -n operators my-trustee-operator
kubectl delete csv -n operators trustee-operator.v0.3.0

3 - Trustee in Docker

Installing Trustee on Docker compose

Use Docker Compose if you want to get Trustee running quickly with minimal prerequisites. This is the recommended starting point for developers evaluating Trustee or building a proof of concept. It requires only Docker and gives you a working KBS, Attestation Service, and RVPS with two commands. For production deployments, consider using Helm or the Trustee Operator install paths.

Installation

Clone the Trustee repo.

git clone https://github.com/confidential-containers/trustee.git && cd trustee

Run Trustee.

docker compose up -d

Admin Setup (Optional)

Trustee admin APIs are protected. An admin keypair is required to use them. Trustee in Docker Compose will automatically generate an admin keypair. The private key, which an admin should provide to the KBS client, will be located at kbs/config/private.key.

You can replace the randomly generated admin keypair with the following commands.

openssl genpkey -algorithm ed25519 > kbs/config/private.key
openssl pkey -in kbs/config/private.key -pubout -out kbs/config/public.pub

Debug Mode (Optional)

To enable additional debug information, you can set the RUST_LOG environment variable.

First, create a file called debug.env.

RUST_LOG=debug

Then, you can run Trustee with an additional argument.

docker compose --env-file debug.env up

Advanced Setup

Docker Compose mounts Trustee configuration files from the Trustee repository itself. Specifically, the KBS configuration file is located in kbs/config/docker-compose/kbs-config.toml, the Attestation Service configuration is in /kbs/config/as-config.json, and the RVPS configuration is in /kbs/config/rvps.json.

These configuration files are read at Trustee startup. If you edit them, restart Trustee (docker compose restart). The configuration options are described here and here.

Advanced Settings

Some advanced settings that you may want to enable include:

  • HTTPS HTTPS can be enabled via the KBS configuration file. HTTPS provides an additional level of security on top of the KBS protocol and should be enabled in production environments.
  • Slim Attestation Token Guests with many devices can create large attestation tokens. In some cases this will outgrow HTTP header limits. When attesting guests with many devices (such as NVIDIA PPCIE), set verbose_token to false in the AS config file.
  • Token Duration The lifetime/duration of the attestation token can be set via the duration_min field of the AS config.

Uninstall

Stop Trustee.

docker compose down