CLI Reference

Type, default, and effect for every flag of every c8s command — install and uninstall, the CDS, allowlist, secrets and volumes, the in-pod fetchers, and the node-side daemons.

One section per command, mirroring the flag definitions in the c8s source. Each table lists every flag of the command above it.

The c8s binary also responds to the symlink aliases get-cert, ratls-mesh, and nri-image-policy (each auto-prepends the matching subcommand).

c8s install

Install the c8s operator, CRDs, attestation-api, and component charts via Helm. Flags are registered with cobra/pflag.

FlagTypeDefaultRequiredDescription
--namespacestringc8s-systemNonamespace to install into
--releasestringc8sNoHelm release name
-f, --valuesstring slicenilNovalues files (repeatable)
--waitbooltrueNowait for the release to become ready (helm --wait)
--install-crdsbooltrueNoinstall chart CRDs (false passes helm --skip-crds)
--webhook-cert-fs-groupint6465532NofsGroup for injected certificate volume
--webhook-cert-key-modestring0640Nooctal mode for injected tls.key
--webhook-get-cert-renew-intervalduration6hNorenewal interval for injected workload certificates
--webhook-get-cert-run-as-userint6465532NorunAsUser for injected get-cert containers
--webhook-get-cert-run-as-groupint6465532NorunAsGroup for injected get-cert containers
--webhook-get-cert-run-as-non-rootbooltrueNoset runAsNonRoot for injected get-cert containers
--single-nodeboolfalseNosingle-node / single-CVM cluster: clear the dedicated-CDS-node selector and taint toleration so every node is CDS-eligible (no role=cds label or dedicated node needed). Sets cds.node.selector={} and cds.node.tolerations=[]
--cvm-modestring""YesCVM deployment shape (orthogonal to --hardware-platform): pod (per-pod confidential VMs via the Kata runtime — every workload pod is a kata CVM; host-side attestation-api/nri/ratls-mesh served by the in-guest counterparts), node (generalized node-as-CVM: our own TDX/SNP nodes are themselves confidential VMs, pods run as ordinary processes; attestation-api + nri baked into the node image), gke (GKE managed confidential VMs), or aks (vTPM /dev/tpm0). All modes render a privileged attestation-api (a hostPath device mount alone does not grant device-cgroup access)
--hardware-platformstringsev-snpNoCPU-level TEE hardware (orthogonal to --cvm-mode): sev-snp (/dev/sev-guest) or tdx (Intel TDX, /dev/tdx-guest). Under --cvm-mode=aks both ride the Azure vTPM (/dev/tpm0, no guest device): sev-snp selects the az-snp shape, tdx selects az-tdx
--debugboolfalseNouse the kata-guest-base DEBUG guest variant (<tag>-debug): kubectl logs/exec work on kata pods, but container I/O becomes readable by the untrusted host and the launch measurement differs from the locked image. Requires --cvm-mode=pod; development only
--image-tagstring""Nocomponent image tag to resolve digests at (default: the CLI build version, or main for an unstamped build); override to pin a specific branch/tag/release
--resolve-digestsbooltrueNoresolve each component image tag to its registry digest (via crane), pin it, and add the resolved images to the NRI allowlist. Pass --resolve-digests=false when supplying digests via -f
--attestbooltrueNodeploy the tls-lb attestation sidecar that serves /.well-known/c8s/ (browser and CLI verification via c8s-verify); --attest=false sets tlsLb.attest.enabled=false and omits it
--node-cidrstring slicenilNoCIDR(s) holding this cluster's node addresses (repeatable / comma-separated); sets cds.sandboxInventoryCIDRs, the only addresses CDS dials for a node's admission inventory. Unset, install reads the cluster and emits one host route (/32 or /128) per node, which does not cover nodes added later; pass a range when the node network is separate
--measurementsstring slicenilNoexpected hex launch measurement(s) of this cluster's CVM (repeatable / comma-separated), taken from the node image's manifest.json. Sets cds.measurements and ratlsMesh.measurements, pinning the internal mesh from first boot; empty = no pinning (UNSAFE). Rejected with --cvm-mode=pod, whose per-pod kata guests carry a different measurement
--image-pull-secretstring""Noname of an existing registry-credential Secret (kubernetes.io/dockerconfigjson) in the release namespace; the chart appends it to every component's imagePullSecrets, so all pods can pull the c8s images from an authenticated registry (e.g. a private mirror) from first start. The Secret itself is never created or managed by the install — the install fails fast if it is missing or has the wrong type
--workload-refstring slicenilNoexisting workload to adopt as a confidential workload, as <cw-id>=<namespace>/<kind>/<name>[:<port>]; repeatable. Kind is any resource exposing a pod template at spec.template (deployment, statefulset, daemonset, or an operator CRD such as <kind>.<group>); install patches the pod template with confidential.ai/cw=<cw-id> once c8s is ready. The optional :<port> is the tls-lb upstream port, required on the ref --upstream selects
--upstreamstring""Noconfidential.ai/cw id of the adopted --workload-ref workload tls-lb routes its catch-all to; derives the mesh-wrapped upstream c8s-<id>.<ns>.svc.cluster.local:<port> from that ref's :<port>. Without this or a verified-https tlsLb.upstream, tls-lb renders no catch-all route until one is attached
--operator-keysstring""Nopath to a PEM bundle of operator EC public keys that authorize c8s allowlist writes; sets cds.operatorKeys. Without it, allowlist writes are disabled (reads still served). See creating the operator credential
--forceboolfalseNoproceed past guarded prompts — currently: install without --operator-keys (allowlist writes disabled). Not needed when values are supplied via -f

c8s uninstall

Uninstall the c8s Helm release and, for a --cvm-mode=pod install, sweep the host-side kata artifacts off every node. helm uninstall unwinds the release resources; the host sweep then removes what that path cannot guarantee (/opt/kata, the containerd drop-in, the multi-GB kata-guest-base image, the RKE2 prep template, and the kata-runtime node labels). Requires the helm and kubectl CLIs on PATH.

FlagTypeDefaultRequiredDescription
--namespacestringc8s-systemNonamespace the release was installed into
--releasestringc8sNoHelm release name
--waitbooltrueNowait for the release deletion to complete (helm --wait); the kata host sweep additionally waits for the kata pods to be gone either way
--kata-sweepbooltrueNoafter the release is deleted, sweep the kata host artifacts off every kata node via a short-lived privileged DaemonSet. Skipped automatically when the release was installed without --cvm-mode=pod
--host-sweep-onlyboolfalseNoskip the helm uninstall and only run the kata host sweep — for a cluster whose release is already gone (e.g. a previous bare helm uninstall) but whose nodes still carry kata artifacts. Uses the chart defaults and the distro detected from the cluster when the release values are unavailable
--forceboolfalseNouninstall even while pods with a kata RuntimeClass are running (they lose their runtime: kata VMs keep running unmanaged but cannot restart)
--delete-crdsboolfalseNoalso delete the ConfidentialWorkload CRD — this deletes every ConfidentialWorkload object in the cluster with it
--delete-namespaceboolfalseNoalso delete the release namespace (and everything left in it, e.g. an operator-created image pull Secret)

c8s render-values

Print the resolved Helm values an install would apply, to stdout — without contacting a cluster. Useful for feeding a GitOps consumer (e.g. a Flux HelmRelease's valuesFrom) instead of recomputing digests and device mappings. Unlike install, the host distro isn't autodetected — pass --distro to pin it. Still needs the registry reachable for the default digest resolution (--resolve-digests=true).

FlagTypeDefaultRequiredDescription
--distrostring""Nohost Kubernetes distro (k8s | rke2); install autodetects this, render-values can't, so pass it when you need it pinned (unset leaves the chart default)
--single-nodeboolfalseNosingle-node / single-CVM cluster: clear the dedicated-CDS-node selector and toleration (cds.node.selector={}, cds.node.tolerations=[])
--cvm-modestring""YesCVM deployment shape (orthogonal to --hardware-platform): pod (per-pod kata CVMs; disables host-side ratls-mesh/attestation-api/nri-image-policy), node (generalized node-as-CVM native TEE device), gke (GKE managed CVMs), or aks (vTPM /dev/tpm0)
--hardware-platformstringsev-snpNoCPU-level TEE hardware (orthogonal to --cvm-mode): sev-snp (/dev/sev-guest) or tdx (Intel TDX, /dev/tdx-guest). Under --cvm-mode=aks both ride the Azure vTPM (/dev/tpm0): sev-snp selects az-snp, tdx selects az-tdx
--measurementsstring slicenilNoexpected hex launch measurement(s) of this cluster's CVM (repeatable / comma-separated), from the node image's manifest.json; emits cds.measurements + ratlsMesh.measurements. Empty = no pinning (UNSAFE). Rejected with --cvm-mode=pod
--debugboolfalseNouse the kata-guest-base DEBUG image variant (requires --cvm-mode=pod)
--resolve-digestsbooltrueNoresolve each component image tag to its registry digest (via crane), pin it, and enable the NRI allowlist derivation
--image-tagstring""Nocomponent image tag to resolve digests at (default: the CLI build version, or main)
--image-pull-secretstring""Noname of an existing dockerconfigjson Secret the chart wires into every component's imagePullSecrets
--operator-keysstring""Nopath to a PEM bundle of operator EC public keys that authorize c8s allowlist writes; the file's content is embedded as cds.operatorKeys in the emitted values (the chart value is PEM content, never a path)
--install-crdsbooltrueNoemit values for chart CRDs (false sets statusMirror.enabled=false, matching install --install-crds=false)
--workload-refstring slicenilNoadopted workload as <cw-id>=<namespace>/<kind>/<name>[:<port>]; repeatable. Used here only to derive --upstream's address (render-values patches nothing)
--upstreamstring""Noconfidential.ai/cw id of the adopted --workload-ref workload tls-lb routes its catch-all to; derives tlsLb.upstream.address c8s-<id>.<ns>.svc.cluster.local:<port> from that ref's :<port>

c8s operator

Run the c8s controller-manager and admission webhook.

FlagTypeDefaultRequiredDescription
--metrics-bind-addressstring:8080Noaddress for Prometheus metrics
--health-probe-bind-addressstring:8081Noaddress for health/readyz probes
--leader-electbooltrueNoenable leader election for HA
--leader-election-namespacestringc8s-systemNonamespace holding the leader-election Lease
--status-mirror-enabledbooltrueNoenable CRD-backed ConfidentialWorkload status mirror controller
--get-cert-imagestring""Noimage reference the webhook injects for get-cert containers (empty = webhook disabled)
--cds-urlstring""NoCDS Service URL the injected get-cert containers POST to
--attestation-api-urlstring""Noattestation-api endpoint (empty = no verification)
--cds-measurementsstring slicenilNoSHA-384 hex launch measurement(s) the injected secret-fetcher container requires CDS to present (repeatable; empty pins none)
--exclude-namespacesstring slicenilNoextra namespaces the startup reinject sweep skips (mirrors webhook.extraExcluded)
--webhook-config-namestring""NoMutatingWebhookConfiguration to patch caBundle (empty = skip)
--webhook-service-namestring""Nowebhook Service name (defaults to c8s)
--webhook-service-namespacestring""Nowebhook Service namespace (defaults to --leader-election-namespace)
--cert-fs-groupint6465532NofsGroup applied to injected pods when unset (-1 disables mutation)
--cert-key-modestring0640Nooctal mode for injected tls.key
--get-cert-renew-intervalduration6hNorenewal interval for injected workload certificates
--get-cert-run-as-userint6465532NorunAsUser for injected get-cert containers
--get-cert-run-as-groupint6465532NorunAsGroup for injected get-cert containers
--get-cert-run-as-non-rootbooltrueNoset runAsNonRoot for injected get-cert containers
--kata-enforceboolfalseNoinject a kata runtimeClassName into workload pods that don't request one and enforce kata RuntimeClasses (set by the chart under kata.enabled)
--hardware-platformstringsev-snpNoCPU TEE the injected confidential kata classes target: sev-snp or tdx (set by the chart to match the RuntimeClasses it renders)
--workload-claims-host-dirstring""Nohost directory holding the nri-image-policy inventory socket (Node-as-CVM); when set, the webhook mounts it into the c8s-cert container and injects --workload-claims so get-cert redeems a sandbox token
--workload-claims-guestboolfalseNoKata shape: the inventory is policy-monitor inside the guest, reached on guest loopback, so the webhook injects --workload-claims with no socket mount

c8s cds

Run the Certificate Distribution Service (CDS). Requires --attestation-api-url and --allowlist-db.

FlagTypeDefaultRequiredDescription
--hoststring0.0.0.0Nolisten host
-p, --portint8443Nolisten port
--log-levelstringinfoNolog level: debug, info, warn, error
--attestation-api-urlstring""YesURL of the attestation-api service
--ca-common-namestringc8s Mesh CANocommon name for the in-memory generated mesh CA
--ca-cert-validityduration8760hNovalidity period of the in-memory mesh CA certificate
--measurementsstring slicenilNoSHA-384 hex launch measurements allowed to call /attest (empty = no pinning, UNSAFE)
--ear-issuerstringcdsNoEAR (Entity Attestation Result) JWT issuer claim
--expected-issuerstring""NoEAR JWT issuer claim required on /sign-csr (empty disables)
--jwt-clock-skewint6430NoEAR JWT exp/nbf/iat clock skew tolerance in seconds
--max-ttlduration24hNoupper bound on /sign-csr leaf TTL
--cert-ttlduration24hNocertificate TTL
--challenge-ttlduration60sNochallenge TTL
--request-timeoutduration5sNoper-request /attest timeout (0 disables)
--max-request-sizeint6465536Nomax request body bytes on write endpoints
--read-timeoutduration10sNoHTTP server read timeout
--read-header-timeoutduration5sNoHTTP server read-header timeout
--write-timeoutduration10sNoHTTP server write timeout
--idle-timeoutduration20sNoHTTP server idle timeout
--max-header-bytesint1048576Nomaximum HTTP request header bytes
--san-validationbooltrueNorequire CSR IP SANs to equal the request source IP (false rejects CSRs carrying IP SANs)
--dns-san-patternstring slicenilNoregex a CSR's DNS SANs may match in full; repeatable, and a SAN passes if it matches any one. The chart always supplies the in-cluster Service DNS pattern and appends a public hostname when tls-lb fronts a routed domain. A CSR carrying DNS SANs is rejected when none are set
--allowed-cn-patternstring""Noregex the CSR Subject CN must match in full (empty disables)
--readiness-intervalduration10sNoreadiness check interval
--min-ca-validityduration1hNo/readyz fails when the loaded mesh CA has less than this remaining lifetime
--allowlist-dbstring""Yespath to the allowlist SQLite database
--allowlist-persistentboolfalseNowhether --allowlist-db is on durable storage; false makes the CDS warn at startup that operator-added digests and the mesh CA do not survive a restart
--sandbox-inventory-cidrstring slicenilNoCIDR(s) holding the node addresses the CDS may dial for a sandbox's admission inventory (repeatable). Required to accept sandbox tokens; bounds the callback to node addresses only
--allowlist-seedstring""Nopath to a JSON allowlist (version + digests map) seeded into the store at startup before serving; missing digests are added, existing entries are left untouched (empty disables seeding)
--operator-keysstring""Nopath to a PEM bundle of pinned operator EC public keys; /allowlist writes (POST/PUT/DELETE) require an operator token signed by one of them (empty = writes disabled, reads still served)
--handoff-measurementsstring slicenilNoSHA-384 hex launch measurements allowed to pull the mesh CA and allowlist via /handoff; requires --operator-keys so both replicas attest the same policy (empty = /handoff disabled)
--handoff-peer-urlstring""Nohttps URL of a surviving CDS peer to adopt the mesh CA and allowlist from on startup via attested /handoff (empty = generate a fresh CA). When set, startup fails closed if the peer cannot be reached, denies handoff, or attests a different operator-key policy. Pins the peer with --handoff-measurements
--handoff-peer-timeoutduration2mNodeadline for adopting the CA from --handoff-peer-url before failing startup
--rate-limitfloat6410Nomax requests per second per source IP on attestation endpoints
--rate-burstint20Nomax burst size per source IP
--rate-limiter-max-entriesint10000Nomax entries in the per-IP rate limiter
--rate-limiter-evict-intervalduration1mNointerval for per-IP rate limiter eviction sweep
--rate-limiter-idle-timeoutduration5mNoidle duration before a per-IP rate limiter entry is evicted
--secrets-max-pathsint1024Nomax distinct secret paths held in memory
--secrets-max-value-bytesint4096Nomax bytes in one secret value
--sandbox-ledger-max-entriesint10000Nomax sandbox-to-inventory bindings held in memory
--token-signer-rotation-intervalduration720hNoEAR signing key rotation interval (0 disables)
--token-signer-overlapduration25hNohow long a retired EAR key stays in JWKS
--token-signer-rotation-jitterfloat640.1NoEAR key rotation jitter
--ratls-platformstringsev-snpNoTEE platform for the RA-TLS serving cert: sev-snp or tdx (snp/az-snp/gcp-snp and az-tdx/gcp-tdx aliases normalized). Empty disables TLS — UNSAFE outside tests
--ratls-cert-ttlduration24hNoRA-TLS certificate TTL

c8s cds request-handoff

Drive the client side of the attested mesh-CA handoff (/handoff) end to end: generate an in-memory signer key, obtain a TEE-bound EAR for it from the peer's /attest-key, pull the recipient-encrypted CA material, and confirm the handed-off CA certificate is the trust root the peer serves on GET /ca. Runs standalone as a live-cluster rollout-continuity probe, inside an attested TEE with access to the local attestation-api. The peer admits only the launch measurements pinned in its --handoff-measurements. Prints a one-line JSON report on stdout; the pulled CA private key never leaves process memory.

FlagTypeDefaultRequiredDescription
--peer-urlstring""Yeshttps URL of the CDS peer to pull the mesh CA from; any other scheme is rejected
--attestation-api-urlstring""YesURL of the local attestation-api, which produces this caller's evidence
--measurementsstring slicenilYesSHA-384 hex launch measurement(s) the peer may present (repeatable / comma-separated); pins both its RA-TLS serving cert and its handoff issuer EAR. Handoff has no accept-any mode — an empty pin is a usage error
--operator-keysstring""YesPEM bundle of operator EC public keys; its canonical hash is bound into both handoff attestations and must match the peer's
--expected-issuerstringcdsNoEAR JWT issuer claim required on the peer's handoff EAR
--timeoutduration2mNooverall deadline, including retries while the peer's handoff EAR bootstraps; must be positive
--log-levelstringinfoNolog level: debug, info, warn, error

Exit codes: 0 verified · 1 usage · 2 handoff or verification failed · 3 endpoint unavailable (unreachable / disabled / still bootstrapping past --timeout).

c8s allowlist

Read and mutate the CDS-served allowlist that nri-image-policy / policy-monitor enforce. It has two layers: a floor of image digests admitted by digest alone, and named workload entries that pin an init/main container set with per-container argv and path policy. Reads are unauthenticated; writes are signed with the operator EC private key whose public half the CDS pins (cds.operatorKeys, set by install --operator-keys). See The Allowlist for usage.

SubcommandArgumentsPurpose
listlist the current allowlist floor and workload entries
export[file]write the full allowlist as canonical JSON to a file (default stdout) for backup or re-upload
diff<file>show how an allowlist file differs from the live allowlist
lint<file|->validate an allowlist file and report semantic findings; never contacts the CDS
inspect-image<ref>resolve an image reference via crane and print its digest plus baked Entrypoint/Cmd; registry-only
add<digest> <image>add a single image digest to the floor (operator key required)
remove<digest> [<digest>...]remove one or more image digests from the floor (operator key required)
upload<file>atomically replace the entire allowlist — floor and workload entries — with the contents of a file (operator key required)
workload listlist workload entries
workload get<name>print one workload entry as canonical JSON
workload apply<file|->upsert workload entries from a file, each replaced whole (operator key required)
workload edit<name>fetch a workload entry, edit it in $EDITOR, and apply the result (operator key required)
workload delete<name> [<name>...]delete one or more workload entries (operator key required)

Persistent flags, registered on every subcommand:

FlagTypeDefaultRequiredDescription
--urlstring""Yestls-lb or direct CDS base URL; required by every subcommand that contacts the CDS (lint and inspect-image do not). A tls-lb front door is trusted through its discovery document and is accepted only when it serves CDS-issued public TLS (discovery reports public_tls.mode=cds); a WebPKI front door is refused, since its public certificate is not bound to the attestation evidence. A direct URL is verified by RA-TLS on the CDS serving cert. Plaintext http:// is refused without --insecure
--measurementsstring slicenilNoallowed SHA-384 hex launch measurement(s) of the attested endpoint (repeatable / comma-separated) — the tls-lb's value for a front door, the CDS's value for a direct URL; empty accepts any attested build (UNSAFE)
--measurements-filestring""Nofile of allowed launch measurements, one hex digest per line
--timeoutduration15sNoper-request timeout
--operator-keystring""Nooperator EC private key PEM file whose public key is pinned on CDS via --operator-keys (env C8S_OPERATOR_KEY; the flag wins); required for writes
-o, --outputstringtextNooutput format: text or json
--insecureboolfalseNodev/test only: allow a plaintext http:// CDS URL, skipping RA-TLS attestation of CDS

Per-subcommand flags:

FlagTypeDefaultRequiredDescription
--exit-codeboolfalseNodiff only: exit non-zero when the file and the live allowlist differ
--onlineboolfalseNolint only: also check each digest exists in its registry via crane
--strictboolfalseNolint, upload: treat lint warnings as fatal (lint errors already fail on their own)
--dry-runboolfalseNoadd, remove: print the intended change without calling CDS; upload: show the diff without replacing the allowlist; workload apply: show the diff without writing any entry
--forceboolfalseNoupload only: upload even if core c8s components are missing from the file
--requirestring slicenilNoupload only: component identifiers that must appear in the uploaded image refs (overrides the default set cds, ratls-mesh, nri-image-policy, attestation-api, nginx)

c8s secrets

Write operator-supplied values into the CDS secret store, and report why a sandbox does or does not receive them. CDS releases a value to a pod when the containers running in that pod's sandbox match a workload entry whose secrets grant covers the path; the grant is written with c8s allowlist workload apply. Values are held in the CDS process and nowhere else, so a CDS restart empties the store. See Secrets.

SubcommandArgumentsPurpose
put<path>store a value at a secret path, read from stdin or --from-file
explainprint the release decision CDS reaches for one sandbox

put sends the bytes exactly as read, including any trailing newline, and prints the byte count. Both subcommands sign their request with the operator EC private key whose public half the CDS pins (cds.operatorKeys, set by install --operator-keys).

Persistent flags, registered on every subcommand:

FlagTypeDefaultRequiredDescription
--urlstring""Yestls-lb or direct CDS base URL. A tls-lb front door is trusted through its discovery document and accepted only when that reports public_tls.mode=cds; a direct URL is verified by RA-TLS on the CDS serving cert. Plaintext http:// is refused without --insecure
--measurementsstring slicenilNoallowed SHA-384 hex launch measurement(s) of the attested endpoint (repeatable / comma-separated) — the tls-lb's value for a front door, the CDS's value for a direct URL; empty accepts any attested build (UNSAFE)
--measurements-filestring""Nofile of allowed launch measurements, one hex digest per line
--timeoutduration15sNoper-request timeout
--operator-keystring""Nooperator EC private key PEM file whose public key is pinned on CDS via --operator-keys (env C8S_OPERATOR_KEY; the flag wins). Both subcommands sign, so one of the two must be set
--insecureboolfalseNodev/test only: allow a plaintext http:// CDS URL, skipping RA-TLS attestation of CDS

Per-subcommand flags:

FlagTypeDefaultRequiredDescription
--from-filestring""Noput only: read the value from this file instead of stdin
--overwriteboolfalseNoput only: replace a value already at the path. Without it an occupied path is refused, and the error names what is there
--dry-runboolfalseNoput only: print the intended change without calling CDS
--sandboxstring""Yesexplain only: sandbox ID to report on. It is carried on the pod's certificate; c8s verify prints it
--jsonboolfalseNoexplain only: print the raw report as JSON

c8s volume

Build an encrypted volume and store its key in the CDS secret store. create packages --source into an erofs image, formats a dm-verity tree over it, encrypts the pair to --out, writes the key blob to --escrow-out, and puts the key at --path in the store. It then prints the pod annotations and the allowlist grant to apply; it modifies no workload. The image is ciphertext and can reach the node by any route, including through the untrusted host, attached as a raw block device with virtio serial c8s-vol-<name>. Needs mkfs.erofs and veritysetup on PATH. The key exists in exactly two places — the CDS process and the escrow file — and a key path is create-only: CDS refuses a --path that already holds a value. See Volumes.

SubcommandArgumentsPurpose
createbuild an encrypted volume image and store its key

Persistent flags, registered on every subcommand:

FlagTypeDefaultRequiredDescription
--urlstring""Yestls-lb or direct CDS base URL, verified as for c8s secrets; not read under --dry-run
--measurementsstring slicenilNoallowed SHA-384 hex launch measurement(s) of the attested endpoint (repeatable / comma-separated); empty accepts any attested build (UNSAFE)
--measurements-filestring""Nofile of allowed launch measurements, one hex digest per line
--timeoutduration15sNoper-request timeout
--operator-keystring""Nooperator EC private key PEM file whose public key is pinned on CDS via --operator-keys (env C8S_OPERATOR_KEY; the flag wins); required for the store write
--insecureboolfalseNodev/test only: allow a plaintext http:// CDS URL, skipping RA-TLS attestation of CDS

create flags:

FlagTypeDefaultRequiredDescription
--namestring""Yesvolume name; forms the device serial c8s-vol-<name>, so at most 12 characters
--sourcestring""Yesdirectory whose contents become the volume
--outstring""Yespath the encrypted image is written to; must not exist
--pathstring""Yessecret-store path for the key, e.g. /tenant-a/volumes/weights; absolute, clean, no wildcards
--escrow-outstring""Yespath the key blob is written to, mode 0600; must not exist. It is the only copy of the key outside CDS
--nodestring""Nonode holding the device; emitted as a nodeSelector on the printed annotations
--work-dirstring""Nodirectory for build intermediates (default: a temp dir); they are removed either way
--dry-runboolfalseNobuild the image and write the escrow file, but do not call CDS

c8s cds-attest

Run the tls-lb attestation + over-encryption sidecar (the c8s-verify/v1 server side). Fronted by the tls-lb nginx (chart flag tlsLb.attest.enabled), it serves the LB's attestation at /.well-known/c8s/attestation, runs the post-quantum handshake, and forwards decrypted tunnel traffic to the backend. It's a chart-managed component, not normally run by hand — see Consumer Verification for the protocol.

FlagTypeDefaultRequiredDescription
--hoststring127.0.0.1Nolisten host (loopback: nginx proxies to it)
-p, --portint8800Nolisten port
--log-levelstringinfoNolog level: debug, info, warn, error
--attestation-api-urlstring""Noattestation-api URL (production evidence source)
--platformstringsnpNoTEE platform: snp | az-snp | az-tdx | tdx
--generationstringgenoaNoAMD processor generation for the browser's bare-SNP verifier (--platform snp only, ignored otherwise): milan | genoa | turin
--serving-cert-filestring""Nopath to the LB serving-leaf PEM (the cert nginx presents); enables the tls-cert attestation binding (?pq=false, report_data binds the leaf's SPKI), re-read per request to follow get-cert rotation
--mesh-identity-cert-filestring""NoTEE-held mesh leaf PEM for the identity-bound post-quantum binding, re-read per request. Separate from --serving-cert-file, which may name a host-visible public TLS credential
--mesh-identity-key-filestring""Noprivate key for --mesh-identity-cert-file, re-read per request
--mesh-identity-ca-filestring""Nomesh CA bundle that issued the identity leaf, re-read per request. All three --mesh-identity-* flags must be set; otherwise the identity-bound post-quantum handshake returns 501 binding_unavailable
--evidence-fixturestring""Nodev only: serve recorded TEE evidence from this file instead of the attestation-api
--session-ttlduration5mNopending-handshake TTL and established-session idle TTL
--read-header-timeoutduration5sNoHTTP read-header timeout
--upstreamstring""Nobackend base URL to forward decrypted traffic to (http:// rides the RA-TLS mesh; https:// does mTLS). Empty uses an echo backend (demo)
--upstream-castring""NoPEM CA bundle to verify an https upstream (the mesh CA)
--upstream-certstring""Noclient cert presented to an https upstream (the CDS-issued LB cert)
--upstream-keystring""Noclient key for --upstream-cert
--upstream-server-namestring""NoSNI / verification name for an https upstream

c8s allowlist-proxy

Publish the CDS allowlist API through tls-lb. Public TLS terminates at the tls-lb nginx; this process makes the second trust hop, verifying CDS's RA-TLS serving certificate before forwarding the request. Path, query, and Authorization header are forwarded byte-for-byte, so the operator token's method/path/body binding survives the hop. It routes /allowlist and /allowlist/ to CDS, answers /healthz itself, and binds loopback only. A chart-managed component, not run by hand — see c8s allowlist for the client side.

FlagTypeDefaultRequiredDescription
--hoststring127.0.0.1Nolisten host; must be a loopback IP (nginx is the public listener)
-p, --portint8801Nolisten port; 1–65535
--cds-urlstring""YesCDS base URL; must be an https (RA-TLS) origin with no credentials, path, query, or fragment
--cds-measurementsstring slicenilNoallowed CDS SHA-384 hex launch measurement(s) (repeatable / comma-separated); empty accepts any attested CDS (UNSAFE)
--attestation-api-urlstring""Noattestation-api URL used to verify CDS evidence
--request-timeoutduration30sNotimeout for one request to CDS; must be positive
--read-header-timeoutduration5sNoHTTP request-header timeout; must be positive

c8s verify

Verify a deployed component's TEE attestation evidence (AMD SEV-SNP or Intel TDX) against the hardware signature chain plus a measurement, TCB, and policy check. Verification runs in-process with attestation-go (the Go port of the attestation-rs engine the cluster runs) — no container runtime is needed; a bare SEV-SNP report needs outbound HTTPS to AMD KDS (kdsintf.amd.com) to fetch its VCEK, bounded by --timeout. Takes a [target] (a URL or host:port) as its positional argument, or --url. c8s cds verify is the same command with CDS presets (--kind cds, default port 8443); --mode stays auto, which resolves to ratls-cert for a CDS target. See the verification guide for the end-to-end workflow.

FlagTypeDefaultRequiredDescription
--urlstring""Notarget URL or host:port (alternative to the positional argument)
--kindstringautoNocomponent being verified: cds, lb, workload, or auto
--modestringautoNoevidence mode: auto, ratls-cert, discovery, or attestation-endpoint
--discovery-pathstring/v1/discoveryNopath of the LB discovery document (discovery mode)
--server-namestring""NoTLS SNI server name (for port-forward / routed domains)
--timeoutduration15sNoper-attempt timeout (evidence fetch and AMD KDS collateral fetch)
--from-filestring""Noverify evidence from a saved PEM certificate or attestation-response JSON instead of dialing
--measurementsstring slicenilNoallowed SHA-384 hex launch measurement(s) (repeatable / comma-separated); empty = no pinning (UNSAFE)
--measurements-filestring""Nofile of allowed launch measurements, one hex digest per line
--operator-keysstring""NoPEM bundle of expected operator public keys; verification fails unless the key set the attested target serves at /operator-keys matches it (--kind cds targets)
--sandbox-idstring""Noexpected CRI pod sandbox ID on the target's leaf; requires --mesh-ca
--mesh-castring""NoPEM bundle of the CDS mesh CA; when set, the target's leaf must chain to it, which is what authenticates the reported sandbox ID
--allow-debugboolfalseNoaccept debug-enabled guests
--min-tcb-bootloaderuint0Nominimum bootloader TCB component (0–255)
--min-tcb-teeuint0Nominimum TEE TCB component (0–255)
--min-tcb-snpuint0Nominimum SNP firmware TCB component (0–255)
--min-tcb-microcodeuint0Nominimum microcode TCB component (0–255)
--expected-report-datastring""Nohex REPORTDATA / TPM-nonce anchor override for bare evidence files (1–64 bytes, exactly as bound by the producer)
-o, --outputstringtextNooutput format: text or json
--show-evidenceboolfalseNoprint the raw report fields

Exit codes are a CI contract: 0 verified · 1 usage · 2 verification/policy failed · 3 evidence unavailable (unreachable / unparseable).

c8s get-cert

Obtain a signed certificate via the CDS attestation flow. Requires --cds-url, --attestation-api-url, and --san.

FlagTypeDefaultRequiredDescription
--cds-urlstring""YesURL of the CDS service (e.g. https://cds:8443)
--cds-measurementsstring""Nocomma-separated SHA-384 hex launch measurements for CDS RA-TLS verification (empty = accept any attested CDS)
--attestation-api-urlstring""YesURL of the local attestation-api (e.g. http://localhost:8400)
-o, --outstring""Nopath to write the signed certificate chain PEM (stdout if omitted)
--ca-outstring""Nopath to write just the mesh CA bundle PEM (the issuer certs trailing the leaf in the CDS chain), e.g. for nginx to serve at a discovery endpoint without a separate ConfigMap
--keystring""Nopath to a PEM private key to use for the CSR (ephemeral if omitted)
--key-outstring""Nopath to write the generated private key PEM (ephemeral keys only)
--key-modestring0600Nooctal mode for generated private key
--sanstring""YesSubject Alternative Name for the certificate (IP address or hostname)
-v, --verboseboolfalseNoenable debug logging
--renew-intervalduration0Nore-obtain the certificate at this interval (0 = run once and exit)
--initial-retry-timeoutduration2mNoretry the first certificate request in-process for up to this long before failing, so a transient CDS/mesh outage during a roll does not crash the init container into kubelet backoff (0 = try once)
--initial-retry-intervalduration2sNodelay between in-process retries of the first certificate request
--reload-nginxbooltrueNoSIGHUP nginx after certificate renewal or watched file changes
--continue-on-initial-errorboolfalseNoin renewal mode, keep running when the first certificate request fails
--reload-watchstring arraynilNofile path to poll for changes and reload nginx when it changes (repeatable)
--reload-watch-intervalduration1mNopoll interval for --reload-watch paths
--discovery-outstring""Nopath to write JSON discovery metadata for the issued certificate and attestation evidence
--discovery-cds-cert-urlstring""Nopublic URL path where the CDS certificate PEM is served
--discovery-mesh-ca-urlstring""Nopublic URL path where the mesh CA PEM is served
--discovery-public-tls-modestringcdsNopublic TLS mode to report in discovery metadata (cds or webpki)
--workload-claimsboolfalseNorequest an inventory-signed sandbox token — which the CDS verifies and stamps into the issued leaf — from the local admission inventory at get-cert's compiled-in Unix socket path (nri-image-policy on Node-as-CVM, policy-monitor in the Kata guest). The path is baked in, not supplied; fails closed if the inventory is unreachable
--workload-claims-guestboolfalseNoreach the inventory on the Kata guest's loopback address instead of the Node-as-CVM Unix socket. Both endpoints are compiled in; this only selects which shape applies, and a wrong setting fails closed
--workload-claims-timeoutduration5sNotimeout for the admission inventory request

c8s get-secret

Fetch the secrets this pod is granted and write each one to a file under --out-dir. Injected by the webhook as a native sidecar. It authenticates to CDS with the pod's CDS-issued certificate and a sandbox token redeemed from the node's admission inventory over a compiled-in socket path, and CDS releases only once every main container in the sandbox is running — earlier attempts are refused and retried, so the files appear shortly after the workload starts and a consumer must wait for them. A path the store does not hold yet is created with a CDS-generated value, which does not survive a CDS restart. After writing, the process idles until the pod is torn down. See Secrets.

FlagTypeDefaultRequiredDescription
--cds-urlstring""Yesbase URL of CDS; must be https (RA-TLS)
--attestation-api-urlstring""Yeslocal attestation-api used to verify CDS's RA-TLS certificate
--measurementsstring slicenilNoSHA-384 hex launch measurement(s) CDS must present (repeatable / comma-separated); empty pins none (UNSAFE)
--certstring/run/c8s/certs/tls.crtNothe pod's CDS-issued certificate, presented to CDS
--keystring/run/c8s/certs/tls.keyNoprivate key for --cert
--secretstring slicenilYesNAME=/store/path to fetch; NAME is the filename written under --out-dir (repeatable). At least one is required, each NAME must be distinct and must not be a path
--out-dirstring/run/c8s/secretsNodirectory the secret files are written to; must be memory-backed
--file-modestring0640Nooctal mode for the written files
--attemptsint60Nohow many times to try before failing; must be positive
--retry-intervalduration5sNowait between attempts; must be positive
--request-timeoutduration10sNoper-request timeout against CDS; must be positive
--inventory-timeoutduration5sNotimeout for redeeming a sandbox token from the node's admission inventory; must be positive

c8s get-volume

Fetch the key for each encrypted volume this pod is granted and hand it to c8s volumed on the node, which opens the device and mounts it read-only into this pod. Injected by the webhook as a native sidecar, with the same authentication, release rule, and retry behavior as c8s get-secret: the volume appears shortly after the workload starts. The key must already be in the store, put there by c8s volume create; nothing here creates one. Linux only — the subcommand is registered only in Linux builds of the CLI. See Volumes.

FlagTypeDefaultRequiredDescription
--cds-urlstring""Yesbase URL of CDS; must be https (RA-TLS)
--attestation-api-urlstring""Yeslocal attestation-api used to verify CDS's RA-TLS certificate
--measurementsstring slicenilNoSHA-384 hex launch measurement(s) CDS must present (repeatable / comma-separated); empty pins none (UNSAFE)
--certstring/run/c8s/certs/tls.crtNothe pod's CDS-issued certificate, presented to CDS
--keystring/run/c8s/certs/tls.keyNoprivate key for --cert
--volumestring slicenilYesNAME=/store/path to open; NAME selects the device by serial c8s-vol-<name> and names the mounted volume (repeatable). At least one is required and each NAME must be distinct
--socket-dirstring/run/c8s/workload-claimsNodirectory holding the node agent's socket, as this pod sees it
--attemptsint60Nohow many times to try before failing; must be positive
--retry-intervalduration5sNowait between attempts; must be positive
--request-timeoutduration10sNoper-request timeout against CDS and the node agent; must be positive
--inventory-timeoutduration5sNotimeout for redeeming a sandbox token from the node's admission inventory; must be positive

c8s volumed

Node agent that opens encrypted volumes for the pods on its node. An injected c8s get-volume sidecar hands it a key over volumed.sock, created inside the admission inventory's socket directory; the daemon resolves the calling pod from kernel peer credentials, opens dm-crypt and dm-verity, and mounts the result read-only into that pod and no other. The mount target is never taken from what the caller reports about itself. Teardown is driven by the pod's cgroup slice disappearing. Runs privileged on every node, and takes no positional arguments. Linux only — the subcommand is registered only in Linux builds of the CLI. See Volumes.

FlagTypeDefaultRequiredDescription
--socket-dirstring""Yeshost directory holding the admission inventory's socket, where this daemon creates volumed.sock. No default: the in-pod path a sidecar sees is not where the daemon serves
--kubelet-rootstring/var/lib/kubeletNokubelet's root directory, holding per-pod volume directories
--cgroup-rootstring/sys/fs/cgroupNocgroup mount, where a pod's slice going away is what triggers teardown
--reap-intervalduration15sNohow often to tear down volumes whose pod has gone; must be positive
--max-mountsint64Nomaximum volumes open on this node at once; must be positive

c8s cred-release

Issue a short-lived kube client certificate to a caller that proves possession of the operator key whose public half was measured into RTMR[3] at node launch. It serves POST /release-credential over RA-TLS — the endpoint c8s get-kubeconfig consumes — signing the caller's CSR with the cluster's client CA and returning a kubeconfig anchored to the serving CA. Startup fails closed if the measured key does not match RTMR[3], and an empty --platform is rejected because RA-TLS is mandatory here. Intel TDX only: the operator-key binding lives in RTMR[3]. Baked as a systemd unit in the c8s node image; not run by hand. The CA defaults are the RKE2 paths — on kubeadm, set all three to /etc/kubernetes/pki/ca.crt and ca.key.

FlagTypeDefaultRequiredDescription
--listenstring:8443NoHTTPS (RA-TLS) bind address
--attestation-api-urlstringhttp://127.0.0.1:8400Nolocal attestation-api base URL, the source of the RA-TLS serving cert's TDX quote
--platformstringtdxNoTEE platform (RTMR is TDX-only); empty is rejected
--client-ca-certstring/var/lib/rancher/rke2/server/tls/client-ca.crtNocluster client-CA cert that signs kube client certs
--client-ca-keystring/var/lib/rancher/rke2/server/tls/client-ca.keyNocluster client-CA key
--server-ca-certstring/var/lib/rancher/rke2/server/tls/server-ca.crtNoCA that signs the apiserver serving cert; embedded in the released kubeconfig
--cert-ttlduration24hNolifetime of issued operator certs
--cert-orgstringsystem:mastersNoKubernetes group (cert Subject O) for the issued cert
--cert-cnstringoperatorNoKubernetes user (cert Subject CN) for the issued cert

c8s get-kubeconfig

Obtain an operator kubeconfig from a measured Intel TDX CVM. The node is attested through its attestation-api and its quote's rtmr_3 must equal the value the operator public key implies (the node was launched to trust that key); a locally generated CSR is then exchanged for a short-lived kube client certificate over the node's cred-release endpoint, and the kubeconfig is written to --out. Verification runs in-process with attestation-go, including the RA-TLS check on the cred-release dial. TDX only — the operator-key binding lives in RTMR[3], so a node reporting any other platform is rejected. Requires --operator-key, --out, and either --node or all of --attest-url, --release-url, and --apiserver-url.

FlagTypeDefaultRequiredDescription
--nodestring""Noguest host/IP that fills --attest-url, --release-url, and --apiserver-url with the standard ports (8400/8443/6443); each explicit URL flag overrides it
--attest-urlstring""Noattestation-api /attest URL
--release-urlstring""Nocred-release base URL
--apiserver-urlstring""Noapiserver URL written into the kubeconfig
--operator-keystring""Yesoperator ECDSA private key PEM; its public half is the one bound into RTMR[3] at node launch, and it signs the credential-release request
--contextstringc8sNokubeconfig cluster/context/user name
--tls-server-namestringc8s-cvmNokubeconfig tls-server-name: pins apiserver certificate verification to this SAN (baked into the node image's tls-san) instead of the dialed IP. Empty omits the field
--outstring""Yespath the kubeconfig is written to, mode 0600
--timeoutduration30sNoper-step network timeout

c8s ratls-mesh

Run the RA-TLS L4 mesh proxy or its iptables side commands.

FlagTypeDefaultRequiredDescription
--platformstringautoNoTEE platform: sev-snp, tdx, or auto (probes /dev/{tdx_guest,sev-guest})
--attestation-api-urlstring""NoURL of the local attestation-api (e.g. http://localhost:8400)
--outbound-portint15001Nooutbound listener port (intercepted app traffic)
--inbound-portint15006Noinbound listener port (RA-TLS from peer nodes)
--node-ipstring""Nothis node's IP (auto-detected from NODE_IP env if unset)
--cert-dns-sanstring""NoDNS SAN placed on the CDS-issued mesh cert (must match CDS --dns-san-pattern; empty omits SANs). Not used for peer verification, which is attestation-based
--log-levelstringinfoNolog level: debug, info, warn, error
--dial-timeoutduration5sNoplain TCP dial timeout
--tls-dial-timeoutduration10sNoRA-TLS dial timeout
--dest-header-timeoutduration5sNoinbound destination header read timeout
--drain-timeoutduration30sNograceful shutdown drain timeout
--keepaliveduration30sNoTCP keepalive interval (0 to disable)
--idle-timeoutduration0Noclose connections idle longer than this (0=disabled)
--max-connsint0Nomax concurrent connections (0=unlimited)
--max-conns-per-sourceint0Nomax concurrent connections per source IP (0=unlimited)
--health-portint15021Nohealth/metrics HTTP port
--measurementsstring""Nocomma-separated hex SHA-384 launch measurements (empty = accept any TEE)
--cert-ttlduration24hNoRA-TLS certificate lifetime (rotates at 50%)
--rotation-timeoutduration30sNomax time for background certificate rotation
--cert-modestringself-signedNocertificate mode: self-signed (default), or cds (boots self-signed, upgrades to CDS-issued in background)
--cds-urlstring""NoCDS service URL for attestation and CA bundle retrieval (required for cds mode)
--ca-certstring""Nopath to CA certificate file for peer verification
--ca-poll-intervalduration5mNointerval to poll CDS /ca for CA bundle updates
--cds-measurementsstring""Nocomma-separated SHA-384 hex launch measurements that CDS's RA-TLS peer cert must match; empty = accept any (UNSAFE outside development)
--session-cache-sizeint64NoTLS session cache size per node (0 disables session resumption)
--access-logbooltrueNoemit per-connection structured access log
--cert-pipeline-probe-urlstring""NoCDS /readyz URL for pipeline health probing (empty = disabled)
--cds-retry-backoffduration2sNoinitial backoff duration for CDS certificate upgrade retries
--cds-retry-max-backoffduration60sNomaximum backoff duration for CDS certificate upgrade retries
--max-dest-header-sizeint256Nomaximum destination header size in bytes
--pipe-buffer-sizeint32768Nobuffer size for TCP pipe forwarding
--accept-error-thresholdint6410Noconsecutive accept errors before marking unhealthy
--health-read-timeoutduration5sNohealth server read timeout
--health-write-timeoutduration10sNohealth server write timeout
--metrics-update-intervalduration10sNointerval for resolver cache and cert expiry metric updates
--local-cidr-boot-timeoutduration1sNosynchronous retry budget at startup for host pod-network CIDR discovery; past this the mesh falls through to the async refresh loop and local-destination validation uses Kubernetes pod HostIP ownership until discovery recovers
--iptables-metrics-filestring/tmp/ratls-iptables-metrics.jsonNoshared file where iptables-sync publishes counters (empty disables)
--cds-op-timeoutduration30sNoper-operation timeout for CDS certificate upgrade and CA bundle refresh
--cert-pipeline-probe-timeoutduration5sNoHTTP client timeout for cert pipeline health probe requests
--cert-pipeline-probe-intervalduration60sNointerval between cert pipeline health probe requests

c8s ratls-mesh iptables-sync

Watch Kubernetes pods and maintain the iptables/ipset rules that redirect mesh traffic.

FlagTypeDefaultRequiredDescription
--outbound-portint15001Nooutbound listener port
--uidint1337NoUID to exclude from redirect
--exclude-uidsstring0Nocomma-separated UIDs to skip (e.g. root=0 so kubelet/containerd can reach registries)
--exclude-source-namespacesstringkube-systemNocomma-separated local source namespaces excluded from transparent mesh interception
--node-ipstring slicenilNolocal node IP(s); repeat or comma-separate for dual-stack (one per family). Defaults to the NODE_IP env. Each address must be a non-loopback, non-unspecified IP bound to a local interface
--resync-periodduration30sNoperiodic full ipset reconciliation interval
--watchdog-periodduration2sNointerval at which the base-chain jump rules are re-asserted at position 1 (bounds the race window against kube-proxy reinserting KUBE-SERVICES)
--ipset-maxelemint262144Nomaximum members per managed ipset
--cw-inbound-passthroughstringudp:53,tcp:53Nocomma-separated proto:source-port replies exempted from the always-on cw inbound guard (which drops FORWARD-path traffic to confidential.ai/cw pods so only mesh-delivered and host-local traffic reaches them). Empty = strict drop-all; DNS is the default
--ready-filestring""Nopath to write after initial ipset and iptables sync succeeds
--iptables-metrics-filestring/tmp/ratls-iptables-metrics.jsonNoshared file where iptables-sync publishes counters (empty disables)
--log-levelstringinfoNolog level: debug, info, warn, error

The ratls-mesh iptables-cleanup subcommand takes no flags.

c8s nri-image-policy

Run the NRI image-policy plugin. Uses the standard Go flag package; most configuration comes from the YAML config file rather than CLI flags.

FlagTypeDefaultRequiredDescription
--configstring/etc/nri/conf.d/image-policy.yamlNopath to config file
--health-addrstring:8080Nohealth check listen address
--read-timeoutduration5sNoHTTP server read timeout
--write-timeoutduration10sNoHTTP server write timeout

c8s probe-file

Exit 0 if <path> exists and is non-empty — a file-existence helper for distroless containers, where /bin/test is not available. One-shot by default (for a kubelet exec probe); with --wait it blocks until the path passes (or --timeout elapses), so it can be the entrypoint of an init container that gates a workload on a file another container writes — the exec-free equivalent of a startup probe, needed on locked kata guests where exec probes are denied by policy. The non-empty check rules out passing on a half-written file.

FlagTypeDefaultRequiredDescription
--waitboolfalseNoblock until <path> passes the check instead of probing once
--poll-intervalduration1sNohow often to re-check <path> in --wait mode
--timeoutduration0Nogive up (non-zero exit) after this long in --wait mode; 0 waits forever