Ingress

View as Markdown

By default, the OpenShell gateway is only reachable inside the cluster. To let CLI clients connect without a kubectl port-forward, expose the gateway through an ingress.

OpenShell uses the Kubernetes Gateway API for ingress. The chart creates a GRPCRoute that routes inbound gRPC traffic to the gateway pod. You need a Gateway API implementation installed on your cluster to fulfill the GRPCRoute. This page uses Envoy Gateway, which the chart is tested with.

Install Envoy Gateway

Envoy Gateway installs the Gateway API CRDs and controller:

$helm install eg \
> oci://docker.io/envoyproxy/gateway-helm \
> --version v1.8.1 \
> --namespace envoy-gateway-system \
> --create-namespace \
> --wait

Create the GatewayClass

Create the eg GatewayClass that the OpenShell chart references:

$kubectl apply -f - <<'EOF'
$apiVersion: gateway.networking.k8s.io/v1
$kind: GatewayClass
$metadata:
$ name: eg
$spec:
$ controllerName: gateway.envoyproxy.io/gatewayclass-controller
$EOF

Verify the GatewayClass is accepted:

$kubectl get gatewayclass eg

The ACCEPTED column should show True.

Install OpenShell with Gateway API enabled

Enable the GRPCRoute and let the chart create a Gateway resource in the openshell namespace:

$helm upgrade --install openshell \
> oci://ghcr.io/nvidia/openshell/helm-chart \
> --version <version> \
> --namespace openshell \
> --set grpcRoute.enabled=true \
> --set grpcRoute.gateway.create=true \
> --set grpcRoute.gateway.className=eg

Get the external address

After the Gateway is provisioned, Envoy Gateway creates a LoadBalancer service in the openshell namespace. Wait for it to get an external address:

$kubectl -n openshell get svc -l gateway.envoyproxy.io/owning-gateway-name=openshell

After the EXTERNAL-IP is assigned, register the gateway with the CLI:

$openshell gateway add http://<external-ip> --name production
$openshell status

This setup is plaintext end-to-end and is intended for development. For external access, terminate TLS at the gateway as shown below.

HTTPS (TLS termination)

Envoy Gateway can terminate TLS at the listener and forward plaintext to the OpenShell gateway pod:

client → HTTPS → Envoy Gateway (terminate TLS) → plaintext → openshell gateway pod

Envoy Gateway only terminates TLS here — it does not perform OIDC. Do not enable an Envoy Gateway OIDC SecurityPolicy in front of the gateway: that flow relies on browser redirects and cookies and cannot work with the OpenShell CLI or headless agents. Instead, the OpenShell gateway validates an OIDC bearer token that the client sends in the gRPC authorization metadata, which Envoy forwards untouched.

Because Envoy terminates TLS, the OpenShell gateway never sees a client certificate, so client mTLS cannot provide identity on this path. Use OIDC bearer tokens for client identity instead.

For headless agents and CI, the CLI obtains the token via the OAuth2 client-credentials grant (no browser): set OPENSHELL_OIDC_CLIENT_SECRET to the OAuth client secret before running openshell gateway add. The client id comes from --oidc-client-id (default openshell-cli); pass it explicitly if your IdP client uses a different id. Interactive human users get the browser-based Authorization Code + PKCE flow by default.

Provide a TLS certificate

Create a kubernetes.io/tls Secret in the openshell namespace with the certificate for your external hostname:

$kubectl -n openshell create secret tls openshell-ingress-tls \
> --cert=tls.crt --key=tls.key

The Secret may also be issued by cert-manager, or you can reference the chart’s existing openshell-server-tls Secret if its SANs include the external hostname.

Install with HTTPS termination

Enable an HTTPS listener, point it at the Secret, disable gateway-pod TLS so Envoy forwards plaintext, and configure an OIDC issuer for client identity:

$helm upgrade --install openshell \
> oci://ghcr.io/nvidia/openshell/helm-chart \
> --version <version> \
> --namespace openshell \
> --set grpcRoute.enabled=true \
> --set grpcRoute.gateway.create=true \
> --set grpcRoute.gateway.className=eg \
> --set grpcRoute.gateway.listener.protocol=HTTPS \
> --set grpcRoute.gateway.listener.port=443 \
> --set 'grpcRoute.gateway.listener.tls.certificateRefs[0].name=openshell-ingress-tls' \
> --set server.disableTls=true \
> --set server.oidc.issuer=https://<issuer> \
> --set 'grpcRoute.hostnames[0]=<external-hostname>'

Keep the certificate Secret in the release namespace. Referencing a Secret in another namespace requires a ReferenceGrant.

Register over HTTPS

$openshell gateway add https://<external-hostname> --name production --oidc-issuer https://<issuer>
$openshell status

See Authentication for OIDC issuer, audience, and roles configuration.

SSH Relay

Sandbox SSH uses the gateway endpoint registered with the CLI. No separate Helm SSH host or port values are required.

Next Steps

Return to Setup to complete the installation.