Skip to main content

Configuration

This page covers two areas of Provisioner configuration: the main configuration file the Provisioner uses to perform its operations, and the Kubernetes RBAC roles and cluster roles required for the Provisioner to manage Kubernetes resources as part of the provisioning process.

Main configuration

The Provisioner is configured via a YAML file. The path to the file is passed as a command-line argument at startup. String values support ${ENV_VAR} substitution and !file <path> directives that load the value from a file on disk — useful for secrets mounted into the container.

info

In a standard k8shell deployment, configuration is managed alongside other k8shell services. This section provides a full reference of all configuration values.

Top-level fields

FieldDefaultDescription
targetNamespacerequiredKubernetes namespace where standalone workspace pods are provisioned.
injectNamespacesList of namespaces where workload injection is permitted. See Injection namespaces.
clusterDomaincluster.localKubernetes cluster domain used to construct workspace pod FQDNs.
defaultRegistryrequiredDefault container registry for workspace images. See Default registry.
k8shellCapabilitiesCapabilities propagated to k8shelld inside each workspace. See k8shell capabilities.
certManagercert-manager integration for workspace TLS certificates. See Cert-manager.
grpcrequiredProvisioner gRPC server configuration. See gRPC.
natsNATS connection and KV store configuration for provisioning job tracking. See NATS.
identityAddress and credentials for the Identity service. See Identity.
jwtVerifierrequiredJWT verification settings for validating workspace identity tokens. See JWT verifier.
blueprintsLocal blueprint directory and fallback settings. See Blueprints.

Injection namespaces

injectNamespaces controls which namespaces the Provisioner is permitted to inject workspaces into:

  • Omitted or empty — injection is fully disabled; all inject requests are rejected.
  • Explicit list — injection is allowed only in the listed namespaces.
  • ["*"] — injection is allowed in any namespace.

Default registry

When a blueprint image field contains a relative path (no hostname), the Provisioner resolves it against defaultRegistry.host. Fully qualified image references are used as-is and are unaffected by this setting.

FieldDefaultDescription
hostrequiredRegistry hostname prepended to relative image paths, e.g. registry.example.com.

Private registry

The private registry is the container registry the Provisioner uses for workspace images. When username and password are both set, the Provisioner automatically creates an imagePullSecret in each workspace namespace and references it in the pod spec.

FieldDefaultDescription
hostrequiredRegistry hostname, e.g. registry.example.com. Supports ${ENV_VAR} substitution.
certCAPath to a custom CA certificate for the registry TLS connection. Use !file <path> to load from disk.
usernameRegistry username. The Provisioner creates an imagePullSecret in each workspace namespace automatically.
passwordRegistry password. Use !file <path> to load from a mounted secret file.

k8shell capabilities

Settings under k8shellCapabilities are propagated into the k8shelld configuration inside each provisioned workspace.

FieldDefaultDescription
apiServerEnabledtrueWhether k8shelld connects to the API Server for credential helpers and user context calls.
saToken.enabledfalseEnable the Kubernetes service account token credential helper inside workspaces.
saToken.cacheTokensfalseCache retrieved service account tokens to reduce API Server calls.
shells.detachedTTL30mHow long a detached PTY shell session is kept alive with no attached client. Accepts Go duration strings (e.g. 30m, 1h). Set to 0s to disable automatic termination.
shells.allowUnlimittedTTLfalseAllow clients to set an unlimited TTL for detached sessions.
shells.allowSessionDetachfalseAllow clients to detach from PTY shell sessions.

Cert-manager

When certManager.enabled is true, the Provisioner creates a cert-manager Certificate resource for each workspace. When disabled, TLS is not configured on the workspace k8shelld gRPC server.

FieldDefaultDescription
enabledfalseEnable cert-manager certificate provisioning for workspaces.
issuer.nameName of the cert-manager Issuer or ClusterIssuer to use. Required when enabled.
issuer.kindIssuer kind: Issuer or ClusterIssuer. Required when enabled.
duration24hRequested certificate lifetime.
renewBefore12hHow long before expiry cert-manager should renew the certificate.

gRPC

The Provisioner exposes a gRPC server consumed by the SSH Proxy and API Server.

FieldDefaultDescription
portrequiredPort the gRPC server listens on.
enableTLSfalseEnable TLS on the gRPC server.
certFilePath to the TLS certificate file. Required when enableTLS is true.
keyFilePath to the TLS private key file. Required when enableTLS is true.
authEnabledfalseRequire JWT authentication on inbound gRPC calls.
audienceExpected JWT audience claim. Required when authEnabled is true.
allowedList of allowed callers identified by Kubernetes service account and optional namespace. Each entry may specify serviceAccount and/or namespace.

NATS

NATS is used to store provisioning job progress and stream status updates to API clients.

FieldDefaultDescription
enabledfalseEnable NATS integration.
urlNATS server URL, e.g. nats://nats.k8shell:4222.
usernameNATS username.
passwordNATS password. Supports ${ENV_VAR} substitution.
kv.provisionBucketTTL48hRetention period for provisioning job data in the NATS KV store. Accepts Go duration strings.

Identity

The Identity service is the source of truth for user authentication and custom blueprint retrieval. The Provisioner connects to it on every provisioning request to verify the user and fetch their blueprint if applicable.

FieldDefaultDescription
addressgRPC address of the Identity service, e.g. identity.k8shell:9020.
tokenFilePathPath to the service token used to authenticate calls to the Identity service.
caCertPathPath to a custom CA certificate for the Identity service TLS connection.
serverNameOverride the TLS server name used when connecting to the Identity service.

JWT verifier

The JWT verifier is used to validate the identity tokens issued by the Identity service and carried inside each workspace.

FieldDefaultDescription
signingMethodrequiredJWT signing algorithm. Must be es256 or rs256.
publicKeyFilePath to the public key file for verifying tokens signed with RS256.
privateKeyFilePath to the private key file for verifying tokens signed with ES256.

Either publicKeyFile or privateKeyFile must be provided.

Blueprints

Platform blueprints are YAML files loaded from a local directory at startup. The Provisioner merges them with any custom blueprints retrieved from the Identity service via the Blueprint Manager.

FieldDefaultDescription
directoryrequiredPath to the directory containing platform blueprint YAML files. Relative paths are resolved from the config file location.
defaultCustomBlueprintBlueprint name to use as a fallback when a custom blueprint is requested but the Identity service returns not-found. If omitted, a not-found error is returned to the caller instead.

RBAC

The Provisioner requires Kubernetes RBAC permissions to create and manage workspace resources during provisioning. Permissions are scoped to specific namespaces — there are no cluster-wide role requirements.

Standalone pod provisioning

A Role and RoleBinding are created in targetNamespace to allow the Provisioner to manage workspace pods and their associated resources.

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: provisioner-inject-<injectNamespace>
namespace: <injectNamespace>
rules:
- apiGroups: ["", "apps", "metrics.k8s.io"]
resources:
- pods
- pods/resize
- pods/exec
- pods/log
- pods/portforward
- pods/attach
- pods/proxy
- pods/binding
- configmaps
- endpoints
- persistentvolumeclaims
- secrets
- events
- services
- services/proxy
- serviceaccounts
verbs: ["create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"]
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["create", "get", "list", "delete", "watch", "update", "patch"]
- apiGroups: ["networking.k8s.io"]
resources: ["networkpolicies"]
verbs: ["create", "delete", "get", "list", "watch", "update", "patch"]
# Added when Cilium is installed:
- apiGroups: ["cilium.io"]
resources: ["ciliumnetworkpolicies"]
verbs: ["create", "delete", "get", "list", "watch", "update", "patch"]
# Added when certManager.enabled is true:
- apiGroups: ["cert-manager.io"]
resources: ["certificates"]
verbs: ["create", "delete", "get", "list", "watch", "update", "patch"]

The cilium.io rule is added only when a CiliumNetworkPolicy CRD is detected in the cluster. The cert-manager.io rule is added only when certManager.enabled is true.

Injection namespaces

A Role and RoleBinding are created in each namespace listed in injectNamespaces, granting the Provisioner the permissions it needs to inject and eject workspaces in that namespace.

warning

Injection namespaces are often owned by third-party applications that manage their own desired state. If such a tool has sync or reconciliation enabled, it may delete or overwrite the Role and RoleBinding that the Provisioner creates, causing injection to fail silently or with permission errors.

For example, if the namespace is managed by Argo CD with automated sync enabled, Argo CD will treat the Provisioner-created resources as out-of-band and prune them on the next sync cycle. To avoid this, either exclude the Provisioner-managed resources from Argo CD's sync scope (e.g. using resource exclusions or the argocd.argoproj.io/managed-by annotation) or disable automated pruning for the affected namespace.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: provisioner-inject
namespace: <injectNamespace>
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
- apiGroups: ["apps"]
resources: ["replicasets"]
verbs: ["get"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "patch"]
- apiGroups: [""]
resources: ["configmaps", "secrets", "services"]
verbs: ["get", "create", "update", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "create"]
- apiGroups: ["networking.k8s.io"]
resources: ["networkpolicies"]
verbs: ["get", "create", "update", "delete", "patch"]
- apiGroups: ["cert-manager.io"]
resources: ["certificates"]
verbs: ["get", "create", "update", "delete"]

One Role and RoleBinding pair is created per namespace. Namespaces are determined by the injectNamespaces configuration field.