Experimental - the Kubernetes deployment path is under active development. Expect rough edges and breaking changes.
This chart deploys the OpenShell gateway into a Kubernetes cluster. It is published as an OCI artifact to GHCR at oci://ghcr.io/nvidia/openshell/helm-chart.
The Kubernetes Agent Sandbox CRDs and controller must be installed on the cluster before deploying OpenShell. Install them with:
kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/latest/download/manifest.yamlhelm install openshell oci://ghcr.io/nvidia/openshell/helm-chart --version <version># Precreate the openshell namespace so we can create the SCC cluster role
oc create ns openshell
# Sandboxes are deployed into the openshell namespace and use the default service account for now
oc adm policy add-scc-to-user privileged -z default -n openshell
# Deploy openshell with overrides to allow SCC assignment of fsGroup and runAsUser for the gateway
helm install openshell oci://ghcr.io/nvidia/openshell/helm-chart --version <version> -n openshell \
--set pkiInitJob.enabled=false \
--set server.disableTls=true \
--set podSecurityContext.fsGroup=null \
--set securityContext.runAsUser=null| Tag | Source | Notes |
|---|---|---|
<semver> (e.g. 0.6.0) |
Tagged GitHub release | Tracks the matching gateway and supervisor image versions. Recommended for production. |
0.0.0-dev |
Latest commit on main |
Floating tag, overwritten on every push. appVersion is dev, so images resolve to the :dev tag. |
0.0.0-dev.<commit-sha> |
A specific commit on main |
Per-commit pin. Chart version and appVersion both use the full 40-character commit SHA, which matches the image tag pushed by CI. |
The dev tags are intended for testing changes ahead of a release. Production deployments should pin to a tagged release.
See values.yaml for source defaults. Selected overlays:
ci/values-gateway.yaml- gateway-only configurationci/values-cert-manager.yaml- cert-manager integrationci/values-keycloak.yaml- Keycloak OIDC integration
By default, a pre-install/pre-upgrade hook Job runs openshell-gateway generate-certs
to create the gateway's server and client mTLS Secrets. The Job uses the gateway image
itself, so air-gapped environments only need to mirror that one image (no separate
openssl/alpine sidecar).
The Job is idempotent:
- Both target Secrets exist: log and exit 0.
- Exactly one exists: fail with
kubectl delete secret -n <ns> <server> <client>recovery hint. - Neither exists: generate a CA, server cert, and client cert; POST both
kubernetes.io/tlsSecrets (tls.crt,tls.key,ca.crt).
Disable with --set pkiInitJob.enabled=false when bringing your own PKI (cert-manager,
external CA, or pre-created Secrets). See certManager.* in values.yaml for the
cert-manager alternative.
| Key | Type | Default | Description |
|---|---|---|---|
| affinity | object | {} |
Affinity rules for the gateway pod. |
| certManager.caSecretName | string | "openshell-ca-tls" |
Secret created for the intermediate CA (Certificate with isCA: true). |
| certManager.certificateDuration | string | "8760h" |
Duration for cert-manager-issued certificates. |
| certManager.certificateRenewBefore | string | "720h" |
Renewal window for cert-manager-issued certificates. |
| certManager.clientCaFromServerTlsSecret | bool | true |
Mount gateway client CA from the server TLS secret's ca.crt (populated by cert-manager for certs issued by a CA Issuer). Avoids a separate openshell-server-client-ca Secret. |
| certManager.enabled | bool | false |
Create cert-manager Issuer and Certificate resources instead of using the PKI bootstrap Job. |
| certManager.serverDnsNames | list | ["openshell","openshell.openshell.svc","openshell.openshell.svc.cluster.local","localhost","openshell.localhost","*.openshell.localhost","host.docker.internal"] |
DNS SANs on the cert-manager-issued server certificate. |
| certManager.serverIpAddresses | list | ["127.0.0.1"] |
IP SANs on the cert-manager-issued server certificate. |
| fullnameOverride | string | "" |
Override the full generated resource name. |
| grpcRoute.enabled | bool | false |
Create a Gateway API GRPCRoute for the gateway service. |
| grpcRoute.gateway.className | string | "eg" |
GatewayClass to reference. Envoy Gateway installs one named "eg". |
| grpcRoute.gateway.create | bool | false |
When true, a Gateway resource is created in the release namespace. Set to false and provide name/namespace to attach to a pre-existing Gateway. |
| grpcRoute.gateway.listener.allowedRoutes | string | "Same" |
"Same" restricts attached routes to the release namespace; "All" allows any namespace. |
| grpcRoute.gateway.listener.port | int | 80 |
Listener port for the generated Gateway resource. |
| grpcRoute.gateway.listener.protocol | string | "HTTP" |
Listener protocol for the generated Gateway resource. |
| grpcRoute.gateway.name | string | "" |
Name of the Gateway resource. Defaults to the chart fullname. |
| grpcRoute.gateway.namespace | string | "" |
Namespace of the Gateway referenced by the GRPCRoute parentRef. Defaults to the release namespace. |
| grpcRoute.hostnames | list | [] |
Hostnames the GRPCRoute matches on. Leave empty to match all hosts. |
| image.pullPolicy | string | "IfNotPresent" |
Gateway image pull policy. |
| image.repository | string | "ghcr.io/nvidia/openshell/gateway" |
Gateway image repository. |
| image.tag | string | "" |
Gateway image tag. Defaults to the chart appVersion when empty. |
| imagePullSecrets | list | [] |
Image pull secrets attached to gateway and helper pods. |
| nameOverride | string | "openshell" |
Override the chart name used in generated resource names. |
| networkPolicy.enabled | bool | true |
Create a NetworkPolicy restricting SSH ingress on sandbox pods to the gateway. |
| nodeSelector | object | {} |
Node selector for the gateway pod. |
| pkiInitJob.enabled | bool | true |
Run a pre-install/pre-upgrade Job that creates gateway and client mTLS Secrets. |
| pkiInitJob.serverDnsNames | list | [] |
Extra DNS SANs to append to the server certificate. |
| pkiInitJob.serverIpAddresses | list | [] |
Extra IP SANs to append to the server certificate. |
| podAnnotations | object | {} |
Extra annotations to add to the gateway pod. |
| podLabels | object | {} |
Extra labels to add to the gateway pod. |
| podLifecycle.terminationGracePeriodSeconds | int | 5 |
Grace period, in seconds, before Kubernetes terminates the gateway pod. |
| podSecurityContext.fsGroup | int | 1000 |
fsGroup assigned to the gateway pod. |
| probes.liveness.failureThreshold | int | 3 |
Liveness probe failure threshold before the container is restarted. |
| probes.liveness.initialDelaySeconds | int | 2 |
Liveness probe initial delay, in seconds. |
| probes.liveness.periodSeconds | int | 5 |
Liveness probe period, in seconds. |
| probes.liveness.timeoutSeconds | int | 1 |
Liveness probe timeout, in seconds. |
| probes.readiness.failureThreshold | int | 3 |
Readiness probe failure threshold before the pod is marked not ready. |
| probes.readiness.initialDelaySeconds | int | 1 |
Readiness probe initial delay, in seconds. |
| probes.readiness.periodSeconds | int | 2 |
Readiness probe period, in seconds. |
| probes.readiness.timeoutSeconds | int | 1 |
Readiness probe timeout, in seconds. |
| probes.startup.failureThreshold | int | 30 |
Startup probe failure threshold before the container is killed. |
| probes.startup.periodSeconds | int | 2 |
Startup probe period, in seconds. |
| probes.startup.timeoutSeconds | int | 1 |
Startup probe timeout, in seconds. |
| replicaCount | int | 1 |
Number of OpenShell gateway replicas. |
| resources | object | {} |
Gateway pod resource requests and limits. |
| securityContext.allowPrivilegeEscalation | bool | false |
Whether the gateway container can gain additional privileges. |
| securityContext.capabilities.drop | list | ["ALL"] |
Linux capabilities dropped from the gateway container. |
| securityContext.runAsNonRoot | bool | true |
Require the gateway container to run as a non-root user. |
| securityContext.runAsUser | int | 1000 |
UID assigned to the gateway container. |
| server.dbUrl | string | "sqlite:/var/openshell/openshell.db" |
Gateway database URL. |
| server.disableTls | bool | false |
Disable TLS entirely - the server listens on plaintext HTTP. Set to true when a reverse proxy / tunnel terminates TLS at the edge. |
| server.enableLoopbackServiceHttp | bool | true |
Enable plaintext HTTP routing for loopback sandbox service URLs on TLS-enabled gateways. |
| server.enableUserNamespaces | bool | false |
Enable Kubernetes user namespace isolation (hostUsers: false) for sandbox pods. Requires Kubernetes 1.33+ with user namespace support available (beta through 1.35, GA in 1.36+), plus a supporting container runtime and Linux 5.12+. When enabled, container UID 0 maps to an unprivileged host UID and capabilities become namespaced. |
| server.grpcEndpoint | string | "" |
gRPC endpoint sandboxes call back into the gateway. Leave empty to derive it from the chart fullname, release namespace, service port, and disableTls flag, for example https://openshell.openshell.svc.cluster.local:8080. Override only when sandboxes must reach the gateway via a different hostname (e.g. an external ingress or a host alias). |
| server.hostGatewayIP | string | "" |
Host gateway IP for sandbox pod hostAliases. When set, sandbox pods get hostAliases entries mapping host.docker.internal and host.openshell.internal to this IP, allowing them to reach services running on the Docker host. Auto-detected by the cluster entrypoint script. |
| server.logLevel | string | "info" |
Gateway log level. |
| server.oidc.adminRole | string | "" |
Role name for admin access. Leave empty (with userRole also empty) for authentication-only mode. Both must be set or both empty. |
| server.oidc.audience | string | "openshell-cli" |
Expected audience claim for the API resource server. This should match the server's --oidc-audience, NOT the CLI client ID. |
| server.oidc.caConfigMapName | string | "" |
Name of a ConfigMap containing a CA certificate bundle (key: ca.crt) for verifying the OIDC issuer's TLS certificate. Required when the issuer uses a non-public CA (e.g. OpenShift ingress, private PKI). |
| server.oidc.issuer | string | "" |
OIDC issuer URL (e.g. https://keycloak.example.com/realms/openshell). |
| server.oidc.jwksTtl | int | 3600 |
JWKS key cache TTL in seconds. |
| server.oidc.rolesClaim | string | "" |
Dot-separated path to the roles array in the JWT claims. Keycloak: "realm_access.roles", Entra ID: "roles", Okta: "groups". |
| server.oidc.scopesClaim | string | "" |
Dot-separated path to the scopes array in the JWT claims. |
| server.oidc.userRole | string | "" |
Role name for standard user access. |
| server.sandboxImage | string | "ghcr.io/nvidia/openshell-community/sandboxes/base:latest" |
Default sandbox image used when requests do not specify one. |
| server.sandboxImagePullPolicy | string | "" |
Kubernetes imagePullPolicy for sandbox pods. Empty = Kubernetes default (Always for :latest, IfNotPresent otherwise). Set to "Always" for dev clusters so new images are picked up without manual eviction. |
| server.sandboxNamespace | string | "" |
Namespace where sandbox pods are created. Defaults to the Helm release namespace (.Release.Namespace) when left empty. |
| server.tls.certSecretName | string | "openshell-server-tls" |
K8s secret (type kubernetes.io/tls) with tls.crt and tls.key for the server. |
| server.tls.clientCaSecretName | string | "openshell-server-client-ca" |
K8s secret with ca.crt for client certificate verification (mTLS). Set to "" to disable mTLS and run HTTPS-only (use OIDC for auth instead). |
| server.tls.clientTlsSecretName | string | "openshell-client-tls" |
K8s secret mounted into sandbox pods for mTLS to the server. |
| server.workspaceDefaultStorageSize | string | "" |
Default storage size for the workspace PVC in sandbox pods. Uses Kubernetes quantity syntax (e.g. "2Gi", "10Gi", "500Mi"). Empty = built-in default (2Gi). |
| service.healthPort | int | 8081 |
Gateway health service port. |
| service.metricsPort | int | 9090 |
Gateway metrics service port. |
| service.port | int | 8080 |
Gateway gRPC/HTTP service port. |
| service.type | string | "ClusterIP" |
Kubernetes Service type for the gateway. |
| serviceAccount.annotations | object | {} |
Annotations to add to the generated service account. |
| serviceAccount.create | bool | true |
Create a service account for the gateway. |
| serviceAccount.name | string | "" |
Existing service account name to use when serviceAccount.create is false. |
| supervisor.image.pullPolicy | string | "" |
Supervisor image pull policy. Defaults to the gateway image pull policy when empty. |
| supervisor.image.repository | string | "ghcr.io/nvidia/openshell/supervisor" |
Supervisor image repository. |
| supervisor.image.tag | string | "" |
Supervisor image tag. Defaults to the chart appVersion when empty. |
| supervisor.sideloadMethod | string | "" |
How the supervisor binary is delivered into sandbox pods. Empty (default) = auto-detect from cluster version: K8s >= v1.35 -> "image-volume" (ImageVolume enabled by default; GA in v1.36) K8s < v1.35 -> "init-container" (copies via init container + emptyDir) On K8s v1.33-v1.34 with the ImageVolume feature gate manually enabled, set this to "image-volume" explicitly. |
| tolerations | list | [] |
Tolerations for the gateway pod. |
Autogenerated from chart metadata using helm-docs v1.14.2