mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-17 05:31:16 +08:00
* feat(helm): add optional PostgreSQL backing store with Secret-based credentials - Add postgres.enabled and postgres.deploy values to control database backend (SQLite vs PostgreSQL) and subchart deployment independently. - Introduce db-secret.yaml template for Opaque Secret with assembled postgresql:// connection string injected via OPENSHELL_DB_URL env var. - Add Bitnami PostgreSQL as optional subchart dependency keyed on postgres.deploy to prevent subchart deployment in external mode. - Externalize JWT signing key file mode via sandboxJwt.secretDefaultMode with 0400 default matching upstream. - Add validation guard for postgres.deploy=true without postgres.enabled. - Add helm unit tests covering internal, external, URL-override, special character encoding, and misconfiguration error paths. - Update README with Kubernetes and OpenShift install examples for bundled and external PostgreSQL configurations. - Add helm dependency build to lint and unittest tasks. * fix(helm): add database backend docs to README.md.gotmpl and regenerate The helm-docs CI check failed because the Database backend section was added directly to README.md instead of README.md.gotmpl. Move the content to the template and regenerate so the check passes. * fix(helm): use Secret-based DB credentials and support existingSecret Replace the inline db-url stringData pattern with a proper Secret containing individual fields plus a uri key. When postgres.deploy=true the Bitnami service-binding secret is referenced directly; when deploy=false users can supply postgres.external.existingSecret to bring their own Secret, or let the chart generate one from the external field values. Also restructures the README database section for clarity, adds helm-unittest coverage for the new secret resolution paths, and fixes a markdown lint issue in the root README. * refactor(helm): move OpenShift e2e script to e2e/rust/ and add mise task Move test-openshift-scenarios.sh from deploy/helm/openshell/ci/ to e2e/rust/e2e-openshift.sh, matching the existing e2e script naming convention. Register it as `e2e:openshift` in tasks/test.toml — not wired into the `test` or `e2e` aggregates so it only runs on explicit invocation against a live OpenShift cluster. * feat(e2e): add database backend scenarios to Kubernetes e2e Extend with-kube-gateway.sh with an optional multi-scenario loop gated by OPENSHELL_E2E_KUBE_DB_SCENARIOS=1. When enabled, the script installs the Helm chart three times — SQLite (default), bundled PostgreSQL, and external PostgreSQL with existingSecret — running the full test suite against each backend. When unset, existing single-install behavior is unchanged. Also adds helm dependency build before helm install, fixing CI failures caused by the missing PostgreSQL subchart dependency. * refactor(helm): simplify PostgreSQL config to two orthogonal controls Replace postgres.deploy and postgres.external.* with two simple controls: - postgres.enabled: deploy the bundled Bitnami PostgreSQL subchart - server.externalDbSecret: name of a pre-existing Secret with a uri key Delete db-secret.yaml — the chart no longer generates Secrets from individual credential fields. Users either get the Bitnami service-binding secret (bundled) or bring their own via server.externalDbSecret. Add validation that postgres.serviceBindings.enabled must stay true when using bundled PostgreSQL, preventing a confusing runtime failure.
349 lines
14 KiB
YAML
349 lines
14 KiB
YAML
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
# Default values for OpenShell
|
|
|
|
# -- Number of OpenShell gateway replicas.
|
|
replicaCount: 1
|
|
|
|
image:
|
|
# -- Gateway image repository.
|
|
repository: ghcr.io/nvidia/openshell/gateway
|
|
# -- Gateway image pull policy.
|
|
pullPolicy: IfNotPresent
|
|
# -- Gateway image tag. Defaults to the chart appVersion when empty.
|
|
tag: ""
|
|
|
|
# Supervisor image - provides the openshell-sandbox binary injected into sandbox
|
|
# pods. tag defaults to appVersion (same as the gateway image) so both stay in
|
|
# sync when the chart is released.
|
|
supervisor:
|
|
image:
|
|
# -- Supervisor image repository.
|
|
repository: ghcr.io/nvidia/openshell/supervisor
|
|
# -- Supervisor image pull policy. Defaults to the gateway image pull policy when empty.
|
|
pullPolicy: ""
|
|
# -- Supervisor image tag. Defaults to the chart appVersion when empty.
|
|
tag: ""
|
|
# -- 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.
|
|
sideloadMethod: ""
|
|
|
|
# -- Image pull secrets attached to gateway and helper pods.
|
|
imagePullSecrets: []
|
|
# -- Override the chart name used in generated resource names.
|
|
nameOverride: "openshell"
|
|
# -- Override the full generated resource name.
|
|
fullnameOverride: ""
|
|
|
|
serviceAccount:
|
|
# -- Create a service account for the gateway.
|
|
create: true
|
|
# -- Annotations to add to the generated service account.
|
|
annotations: {}
|
|
# -- Existing service account name to use when serviceAccount.create is false.
|
|
name: ""
|
|
|
|
sandboxServiceAccount:
|
|
# -- Create a service account for sandbox pods.
|
|
create: true
|
|
# -- Annotations to add to the generated sandbox service account.
|
|
annotations: {}
|
|
# -- Existing service account name for sandbox pods when sandboxServiceAccount.create is false.
|
|
name: ""
|
|
|
|
# -- Extra annotations to add to the gateway pod.
|
|
podAnnotations: {}
|
|
# -- Extra labels to add to the gateway pod.
|
|
podLabels: {}
|
|
|
|
podSecurityContext:
|
|
# -- fsGroup assigned to the gateway pod.
|
|
fsGroup: 1000
|
|
|
|
securityContext:
|
|
# -- Require the gateway container to run as a non-root user.
|
|
runAsNonRoot: true
|
|
# -- UID assigned to the gateway container.
|
|
runAsUser: 1000
|
|
# -- Whether the gateway container can gain additional privileges.
|
|
allowPrivilegeEscalation: false
|
|
capabilities:
|
|
# -- Linux capabilities dropped from the gateway container.
|
|
drop:
|
|
- ALL
|
|
|
|
service:
|
|
# -- Kubernetes Service type for the gateway.
|
|
type: ClusterIP
|
|
# -- Gateway gRPC/HTTP service port.
|
|
port: 8080
|
|
# -- Gateway health service port.
|
|
healthPort: 8081
|
|
# -- Gateway metrics service port.
|
|
metricsPort: 9090
|
|
|
|
# Pod restart behavior and health probe tuning.
|
|
podLifecycle:
|
|
# -- Grace period, in seconds, before Kubernetes terminates the gateway pod.
|
|
terminationGracePeriodSeconds: 5
|
|
|
|
probes:
|
|
startup:
|
|
# -- Startup probe period, in seconds.
|
|
periodSeconds: 2
|
|
# -- Startup probe timeout, in seconds.
|
|
timeoutSeconds: 1
|
|
# -- Startup probe failure threshold before the container is killed.
|
|
failureThreshold: 30
|
|
liveness:
|
|
# -- Liveness probe initial delay, in seconds.
|
|
initialDelaySeconds: 2
|
|
# -- Liveness probe period, in seconds.
|
|
periodSeconds: 5
|
|
# -- Liveness probe timeout, in seconds.
|
|
timeoutSeconds: 1
|
|
# -- Liveness probe failure threshold before the container is restarted.
|
|
failureThreshold: 3
|
|
readiness:
|
|
# -- Readiness probe initial delay, in seconds.
|
|
initialDelaySeconds: 1
|
|
# -- Readiness probe period, in seconds.
|
|
periodSeconds: 2
|
|
# -- Readiness probe timeout, in seconds.
|
|
timeoutSeconds: 1
|
|
# -- Readiness probe failure threshold before the pod is marked not ready.
|
|
failureThreshold: 3
|
|
|
|
# -- Gateway pod resource requests and limits.
|
|
resources: {}
|
|
|
|
# -- Node selector for the gateway pod.
|
|
nodeSelector: {}
|
|
|
|
# -- Tolerations for the gateway pod.
|
|
tolerations: []
|
|
|
|
# -- Affinity rules for the gateway pod.
|
|
affinity: {}
|
|
|
|
# Server configuration
|
|
server:
|
|
# -- Gateway log level.
|
|
logLevel: info
|
|
# -- Namespace where sandbox pods are created. Defaults to the Helm release
|
|
# namespace (.Release.Namespace) when left empty.
|
|
sandboxNamespace: ""
|
|
# -- Gateway database URL (used for the default SQLite backend).
|
|
dbUrl: "sqlite:/var/openshell/openshell.db"
|
|
# -- Name of a pre-existing Opaque Secret containing a PostgreSQL
|
|
# connection URI (key: uri). When set, the gateway reads OPENSHELL_DB_URL
|
|
# from this Secret instead of using dbUrl. The Secret must contain a
|
|
# `uri` key, e.g. postgresql://user:pass@host:5432/dbname.
|
|
externalDbSecret: ""
|
|
# -- Default sandbox image used when requests do not specify one.
|
|
sandboxImage: "ghcr.io/nvidia/openshell-community/sandboxes/base:latest"
|
|
# -- 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.
|
|
sandboxImagePullPolicy: ""
|
|
# -- Default storage size for the workspace PVC in sandbox pods.
|
|
# Uses Kubernetes quantity syntax (e.g. "2Gi", "10Gi", "500Mi").
|
|
# Empty = built-in default (2Gi).
|
|
workspaceDefaultStorageSize: ""
|
|
# -- 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).
|
|
grpcEndpoint: ""
|
|
# TLS configuration for the server. The server always terminates mTLS
|
|
# directly and requires client certificates.
|
|
# -- 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.
|
|
hostGatewayIP: ""
|
|
# -- 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.
|
|
enableUserNamespaces: false
|
|
# -- Disable TLS entirely - the server listens on plaintext HTTP.
|
|
# Set to true when a reverse proxy / tunnel terminates TLS at the edge.
|
|
disableTls: false
|
|
# -- Enable plaintext HTTP routing for loopback sandbox service URLs on
|
|
# TLS-enabled gateways.
|
|
enableLoopbackServiceHttp: true
|
|
auth:
|
|
# -- UNSAFE: accept unauthenticated CLI/user requests as a local developer
|
|
# principal. Intended only for trusted local Skaffold/k3d development or a
|
|
# fully trusted fronting proxy. Leave false for shared or production clusters.
|
|
allowUnauthenticatedUsers: false
|
|
tls:
|
|
# -- K8s secret (type kubernetes.io/tls) with tls.crt and tls.key for the server.
|
|
certSecretName: openshell-server-tls
|
|
# -- K8s secret with ca.crt for client certificate verification (mTLS).
|
|
# Set to "" to disable mTLS and run HTTPS-only (use OIDC for auth instead).
|
|
clientCaSecretName: openshell-server-client-ca
|
|
# -- K8s secret mounted into sandbox pods for mTLS to the server.
|
|
clientTlsSecretName: openshell-client-tls
|
|
# Gateway-minted sandbox JWT signing keys. The pre-install certgen hook
|
|
# generates an Ed25519 keypair and writes it to a secret containing
|
|
# signing.pem (PKCS#8), public.pem (SPKI), and kid (plain text).
|
|
sandboxJwt:
|
|
# -- Name of the Opaque Secret holding the signing key material. Empty
|
|
# falls back to the chart fullname with "-jwt-keys" appended.
|
|
signingSecretName: ""
|
|
# -- Stable gateway identity embedded in iss/aud of every minted token.
|
|
# Defaults to the release name so HA replicas share identity.
|
|
gatewayId: ""
|
|
# -- Token TTL in seconds. Defaults to 3600 (1h).
|
|
ttlSecs: 3600
|
|
# -- Lifetime (seconds) of the projected ServiceAccount token kubelet
|
|
# writes into each sandbox pod for the IssueSandboxToken bootstrap
|
|
# exchange. Kubelet enforces a minimum of 600s; the driver clamps
|
|
# values outside [600, 86400]. Default 3600 — generous, since the
|
|
# supervisor consumes the token within seconds of pod start.
|
|
k8sSaTokenTtlSecs: 3600
|
|
# -- File mode for the mounted JWT signing key Secret. Default 0400
|
|
# (owner-read only). Override to 0440 or 0444 if the container UID
|
|
# does not match the volume file owner.
|
|
secretDefaultMode: ""
|
|
# OIDC (OpenID Connect) configuration for JWT-based authentication.
|
|
# When issuer is set, the server validates Bearer tokens on gRPC requests.
|
|
oidc:
|
|
# -- OIDC issuer URL (e.g. https://keycloak.example.com/realms/openshell).
|
|
issuer: ""
|
|
# -- Expected audience claim for the API resource server.
|
|
# This should match the server's --oidc-audience, NOT the CLI client ID.
|
|
audience: "openshell-cli"
|
|
# -- JWKS key cache TTL in seconds.
|
|
jwksTtl: 3600
|
|
# -- Dot-separated path to the roles array in the JWT claims.
|
|
# Keycloak: "realm_access.roles", Entra ID: "roles", Okta: "groups".
|
|
rolesClaim: ""
|
|
# -- Role name for admin access. Leave empty (with userRole also empty) for
|
|
# authentication-only mode. Both must be set or both empty.
|
|
adminRole: ""
|
|
# -- Role name for standard user access.
|
|
userRole: ""
|
|
# -- Dot-separated path to the scopes array in the JWT claims.
|
|
scopesClaim: ""
|
|
# -- 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).
|
|
caConfigMapName: ""
|
|
|
|
# Bundled PostgreSQL backing store (Bitnami subchart).
|
|
# Set enabled=true to deploy a PostgreSQL instance alongside the gateway.
|
|
# For external PostgreSQL, leave enabled=false and set server.externalDbSecret
|
|
# to a pre-existing Secret containing a `uri` key.
|
|
postgres:
|
|
# -- Deploy the bundled Bitnami PostgreSQL subchart.
|
|
enabled: false
|
|
# Values below configure the bundled Bitnami PostgreSQL subchart
|
|
# (aliased as "postgres" in Chart.yaml). The subchart uses these to
|
|
# initialise the PostgreSQL instance.
|
|
auth:
|
|
username: openshell
|
|
password: ""
|
|
database: openshell
|
|
# Bitnami service-binding Secrets — must stay true. The gateway reads
|
|
# the connection URI from the subchart-managed Secret.
|
|
serviceBindings:
|
|
enabled: true
|
|
primary:
|
|
persistence:
|
|
enabled: true
|
|
|
|
# NetworkPolicy restricting SSH ingress on sandbox pods to the gateway only.
|
|
networkPolicy:
|
|
# -- Create a NetworkPolicy restricting SSH ingress on sandbox pods to the gateway.
|
|
enabled: true
|
|
|
|
# PKI bootstrap via a pre-install/pre-upgrade hook Job.
|
|
# Runs `openshell-gateway generate-certs` to create the server and client TLS
|
|
# Secrets in-cluster. Key material is written directly to K8s Secrets and
|
|
# never appears in Helm release history. Idempotent: existing secrets are
|
|
# left untouched on upgrade. Reuses the gateway image - no extra image to
|
|
# mirror in air-gapped environments.
|
|
#
|
|
# The server certificate already includes the built-in cluster SANs
|
|
# (`openshell`, `openshell.openshell.svc`, the cluster.local FQDN, `localhost`,
|
|
# `openshell.localhost`, `*.openshell.localhost`, `host.docker.internal`, and
|
|
# `127.0.0.1`) baked into the gateway binary. The lists below are additional
|
|
# SANs appended on top. Wildcard DNS SANs also enable sandbox service URLs under
|
|
# that domain, for example `*.apps.example.com` enables
|
|
# `<sandbox>--<service>.apps.example.com`.
|
|
pkiInitJob:
|
|
# -- Run a pre-install/pre-upgrade Job that creates gateway and client mTLS Secrets.
|
|
enabled: true
|
|
# -- Extra DNS SANs to append to the server certificate.
|
|
serverDnsNames: []
|
|
# -- Extra IP SANs to append to the server certificate.
|
|
serverIpAddresses: []
|
|
|
|
# cert-manager Certificate/Issuer resources (requires cert-manager CRDs in-cluster).
|
|
# Uses namespaced Issuers only (no ClusterIssuer). Does not install cert-manager itself.
|
|
certManager:
|
|
# -- Create cert-manager Issuer and Certificate resources instead of using the PKI bootstrap Job.
|
|
enabled: false
|
|
# -- Secret created for the intermediate CA (Certificate with isCA: true).
|
|
caSecretName: openshell-ca-tls
|
|
# -- 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.
|
|
clientCaFromServerTlsSecret: true
|
|
# -- Duration for cert-manager-issued certificates.
|
|
certificateDuration: 8760h
|
|
# -- Renewal window for cert-manager-issued certificates.
|
|
certificateRenewBefore: 720h
|
|
# -- DNS SANs on the cert-manager-issued server certificate.
|
|
serverDnsNames:
|
|
- openshell
|
|
- openshell.openshell.svc
|
|
- openshell.openshell.svc.cluster.local
|
|
- localhost
|
|
- openshell.localhost
|
|
- "*.openshell.localhost"
|
|
- host.docker.internal
|
|
# -- IP SANs on the cert-manager-issued server certificate.
|
|
serverIpAddresses:
|
|
- 127.0.0.1
|
|
|
|
# Kubernetes Gateway API - HTTPRoute and Gateway resources.
|
|
# Requires a Gateway API controller in the cluster. Install Envoy Gateway via
|
|
# the skaffold.yaml releases or independently:
|
|
# helm install eg oci://docker.io/envoyproxy/gateway-helm \
|
|
# --version v1.4.1 -n envoy-gateway-system --create-namespace
|
|
grpcRoute:
|
|
# -- Create a Gateway API GRPCRoute for the gateway service.
|
|
enabled: false
|
|
# -- Hostnames the GRPCRoute matches on. Leave empty to match all hosts.
|
|
hostnames: []
|
|
gateway:
|
|
# -- 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.
|
|
create: false
|
|
# -- GatewayClass to reference. Envoy Gateway installs one named "eg".
|
|
className: "eg"
|
|
# -- Name of the Gateway resource. Defaults to the chart fullname.
|
|
name: ""
|
|
# -- Namespace of the Gateway referenced by the GRPCRoute parentRef.
|
|
# Defaults to the release namespace.
|
|
namespace: ""
|
|
# Listener settings (only used when gateway.create is true).
|
|
listener:
|
|
# -- Listener port for the generated Gateway resource.
|
|
port: 80
|
|
# -- Listener protocol for the generated Gateway resource.
|
|
protocol: HTTP
|
|
# -- "Same" restricts attached routes to the release namespace; "All" allows any namespace.
|
|
allowedRoutes: Same
|