Skip to main content
Version: 1.19.0 (latest)

Kubernetes

Kasm Workspaces core services can be deployed to Kubernetes using the open-source Kasm Helm chart, which will be Generally Available as of Kasm version 1.19.0 (the developer preview is available using chart version 1.1190.0).

Planning your deployment?

Not sure which components you need? The Helm chart does not cover everything — what you provision alongside it depends on your session types (Docker containers, RDP, VNC) and whether you are running multiple zones. See Kubernetes Deployment Options for a full breakdown before you start.


Quick Start

If you have a running Kubernetes cluster and just want to get Kasm up quickly, here are the minimal steps. See Installation below for the full walkthrough with all options.

Prerequisites: Kubernetes 1.24+, Helm 3.18.x+, a domain name, and a TLS certificate or cert-manager.

Create a namespace and install your TLS certificate as a Kubernetes secret (see Configure TLS Certificates for the available methods), then create a minimal values file:

# my-values.yaml
publicAddr: kasm.example.com
certificate:
secretName: {CERTIFICATE_SECRET_NAME}

Install the chart:

kubectl create namespace {NAMESPACE}
helm install {RELEASE_NAME} oci://registry-1.docker.io/kasmweb/kasm-helm \
--version 1.1190.0 -n {NAMESPACE} -f my-values.yaml

Wait for pods to be ready, then retrieve the admin password:

kubectl get pods -n {NAMESPACE} --watch
kubectl get secret --namespace {NAMESPACE} {RELEASE_NAME}-secrets \
-o jsonpath="{.data.admin-password}" | base64 -d; echo

Point your DNS for publicAddr to the address shown by kubectl get ingress -n {NAMESPACE} and log in at https://{publicAddr} with admin@kasm.local.

caution

After a successful install, disable the one-time initialization jobs before any future helm upgrade:

dbManagement:
initialize: false
upgrade:
enable: false

Architecture Overview

The Kasm Helm chart deploys the core control-plane services inside a Kubernetes cluster. Containerized desktop and application sessions are not run inside the cluster; they are hosted on external Docker Agent servers that you provision separately (either as static agents or via auto scaling). RDP sessions are routed to external Windows or Linux hosts running RDP servers.

The following diagram shows the main components and how traffic flows between them:

Multi-Zone Architecture

Kasm supports multiple deployment zones, which are commonly used to serve users across geographic regions but can also be used to segment groups of users or isolate different workload types across separate pools of compute resources. In a multi-zone deployment, each zone runs its own set of API-layer and proxy-layer services. Additional zones only receive the App role from the Helm chart — their proxy layer is deployed separately using the multi-zone proxy instructions.

Key points to note:

  • Agents are not included in the Helm chart. The Kasm Agent, which hosts containerized sessions (desktops, browsers, apps), must be deployed on separate Docker hosts outside the cluster. You can add agents manually as static servers or configure auto scaling to provision them on demand.
  • RDP over port 3389 requires extra configuration. Standard Kubernetes Ingress only handles HTTP/HTTPS traffic on port 443. By default, thick-client RDP connections route through the RDP HTTPS Gateway on port 443, which works out of the box. To support direct RDP connections on port 3389, you must expose the RDP Gateway via a NodePort or LoadBalancer service. See Direct RDP Connections on Kubernetes for setup instructions.
  • Ingress acts as the external load balancer. All browser and HTTPS-based client traffic enters the cluster through the Ingress controller, which should be backed by a cloud load balancer or similar in production.

Prerequisites

Before installing, ensure you have:

  • Kubernetes 1.24+
  • Helm 3.18.x+: install from helm.sh
  • kubectl configured and connected to your target cluster
  • A default StorageClass (or explicit storageClassName in your values): required for the built-in PostgreSQL database PVC. Not needed if using a standalone external database. Run kubectl get storageclass to verify a default is set.
  • A domain name with DNS control, to use as the publicAddr for Kasm
  • A TLS certificate or cert-manager installed in your cluster. See Configure TLS Certificates for Kasm on Kubernetes

Note that Helm chart versions are based upon Kasm versions, for example chart version 1.1190.0 corresponds to Kasm version 1.19.0, with the minor (middle) number corresponding to the officially supported Kasm version.

Using a managed Kubernetes service?

If you are deploying on a managed Kubernetes platform such as Amazon EKS, Google GKE, or Azure AKS, ensure that your cloud provider's CLI tools are installed and configured (e.g., aws, gcloud, az) and that your kubectl context is pointed at the correct cluster. Refer to your provider's documentation for cluster setup and authentication:

Cloud-hosted deployments may also benefit from using a managed database service (e.g., Amazon RDS, Cloud SQL, Azure Database for PostgreSQL) instead of the built-in database. See the chart's database values for external database configuration.


Installation

Developer Preview Helm Chart

If you are using a developer preview version of the Kasm Helm chart, be aware that no clean migration path to future updates is guaranteed. Review the Developer Preview Builds warnings before proceeding.

0. Verify Your Cluster

Before proceeding, confirm that your cluster is reachable and that nodes are healthy:

kubectl cluster-info
kubectl get nodes

All nodes should show a Ready status. If not, resolve any cluster issues before continuing.


1. Create the Namespace

kubectl create namespace {NAMESPACE}

2. Configure TLS

Install your TLS certificate into the namespace as a Kubernetes secret. See Configure TLS Certificates for Kasm on Kubernetes for the available methods.

Note the secret name you create, as you will need it as {CERTIFICATE_SECRET_NAME} in the next step.


3. Create Your Values File

Create a my-values.yaml file. At minimum, include:

publicAddr: kasm.example.com
certificate:
secretName: {CERTIFICATE_SECRET_NAME}

Refer to the chart definition for a list of all available configuration options (documented in /charts/kasm/values.yaml).

Customizing Component Image Tags

By default, each component uses rolling image tags which pull the latest at time of deployment. To pin a specific build, override the tag field for each component in your values file:

components:
proxy:
image:
tag: 1.19.0-rolling-20260215
api:
image:
tag: 1.19.0-rolling-20260215
manager:
image:
tag: 1.19.0-rolling-20260215
guac:
image:
tag: 1.19.0-rolling-20260215
rdpGateway:
image:
tag: 1.19.0-rolling-20260215
rdpHttpsGateway:
image:
tag: 1.19.0-rolling-20260215

database:
image:
tag: 1.19.0-rolling-20260215

You can override any subset of components independently; omitted components continue to use the chart's default tag.

note

To apply tag changes to a running deployment after initial install, see Applying Changes to a Running Instance below.

deploymentSize Variable Value

deploymentSize controls resource allocation across all Kasm components.

Three values are supported: small, medium, and large. Each value maps to a preset that sets CPU and memory requests/limits and scales the replica count for each component (1/2/3 respectively). The database StatefulSet always runs as a single replica regardless of size.

Choose small for evaluation, single-node, or low-concurrency deployments. Use medium or large for production environments where session throughput and availability matter. Any component's resources or replica count can be overridden individually via components.<name>.resources and components.<name>.replicas when the preset does not match your workload.


4. (Optional) Pre-Create Kasm Secrets

By default, the Helm chart auto-generates random credentials during installation and stores them in a Kubernetes secret. If you prefer to use your own credentials, create the secret before installing the chart.

The secret must be named {RELEASE_NAME}-secrets, where {RELEASE_NAME} is the name you will pass to helm install in the next step. For example, if you plan to run helm install kasm ..., the secret must be named kasm-secrets.

apiVersion: v1
kind: Secret
metadata:
name: {RELEASE_NAME}-secrets
namespace: {NAMESPACE}
type: Opaque
data:
admin-password: "<base64-encoded value>"
user-password: "<base64-encoded value>"
db-password: "<base64-encoded value>"
manager-token: "<base64-encoded value>"
service-token: "<base64-encoded value>"

Apply it with:

kubectl apply -f kasm-secrets.yaml
tip

To base64-encode a value: echo -n 'my-password' | base64

If the chart finds an existing secret with this name during installation, it will use those values instead of generating new ones.


5. Install the Chart

The Kasm Helm chart is available as an OCI Helm chart and from a classic Helm repository.

helm install {RELEASE_NAME} oci://registry-1.docker.io/kasmweb/kasm-helm \
--version 1.1190.0 -n {NAMESPACE} -f my-values.yaml

Classic Helm Repository

helm repo add kasm https://helm.kasm.com
helm repo update
helm install {RELEASE_NAME} kasm/kasm-helm --version 1.1190.0 -n {NAMESPACE} -f my-values.yaml
After a successful install

Once the installation completes, disable the one-time initialization jobs in your values file before running any future helm upgrade. Leaving them enabled will cause them to re-run on every upgrade:

dbManagement:
initialize: false
upgrade:
enable: false
Modifying the chart locally

To customize the Helm chart beyond what values allow, clone the kasm-helm GitHub repository and check out the tagged release that corresponds to your Kasm version (e.g., release/1.1190.0):

git clone https://github.com/kasmtech/kasm-helm.git
cd kasm-helm
git checkout release/1.1190.0

Then install from the local chart directory:

helm install {RELEASE_NAME} ./charts/kasm-helm -n {NAMESPACE} -f my-values.yaml

6. Verify All Pods Are Running

kubectl get pods -n {NAMESPACE} --watch

Wait until all pods show Running or Completed, then press Ctrl+C.


Post-Installation

Configure DNS

Retrieve the ingress address assigned to your deployment:

kubectl get ingress -n {NAMESPACE}

Update your DNS record for publicAddr to point to the value in the ADDRESS column. Once DNS has propagated, Kasm will be reachable at https://{publicAddr}.

Retrieve Credentials

The quickest way to see all post-install information is:

helm get notes {RELEASE_NAME} -n {NAMESPACE}

Or retrieve credentials directly:

# Admin password (login: admin@kasm.local)
kubectl get secret --namespace {NAMESPACE} {RELEASE_NAME}-secrets \
-o jsonpath="{.data.admin-password}" | base64 -d; echo

# User password (login: user@kasm.local)
kubectl get secret --namespace {NAMESPACE} {RELEASE_NAME}-secrets \
-o jsonpath="{.data.user-password}" | base64 -d; echo

Pulling the Latest Build

The chart uses rolling image tags which are rebuilt with the latest software updates and patches on a regular schedule. While Kubernetes does not automatically check for newer images for a running service, you can trigger updates by restarting each service and ensuring the imagePullPolicy is set to Always (which is the chart's default).

Locking in a specific build

If you need to pin a specific build, you can pin to a timestamped tag such as 1.19.0-rolling-20260215 following the section Customizing Component Image Tags. Timestamped tags are immutable so a rollout restart will not pull a newer build. To advance to a newer timestamped build, update the tag in your values file and run helm upgrade.

Use the command kubectl rollout restart to restart services and pull updates. This type of restart will respect the uptime policies in the chart and minimize disruptions.

kubectl rollout restart deployment/{RELEASE_NAME}-api \
deployment/{RELEASE_NAME}-manager \
deployment/{RELEASE_NAME}-proxy \
deployment/{RELEASE_NAME}-guac \
deployment/{RELEASE_NAME}-rdp-gateway \
deployment/{RELEASE_NAME}-rdp-https-gateway \
-n {NAMESPACE}

Monitor rollout progress for any individual deployment:

kubectl rollout status deployment/{RELEASE_NAME}-api -n {NAMESPACE}
Multi-zone deployments

If you configured kasmZones, each zone creates its own set of Deployments with the zone name appended (for example, {RELEASE_NAME}-api-{ZONE_NAME}). Run kubectl get deployments -n {NAMESPACE} to list all Deployments in your namespace before restarting.


Applying Changes to a Running Instance

To apply changes to your values for a running deployment, always set dbManagement.initialize to false. If left enabled, the one-time initialization job will re-run and fail on an already-initialized database.

The value of dbManagement.upgrade.enable depends on whether the change includes a database schema migration. If applying a config change or image tag update with no schema migration (typical of rolling updates) you should set upgrade.enable to false in addition to your other changes:

dbManagement:
initialize: false
upgrade:
enable: false

If an image tag update includes a database schema migration (typical of major/minor version updates, e.g. 1.18.0 -> 1.18.1), then set the value to true:

dbManagement:
initialize: false
upgrade:
enable: true

When upgrade.enable: true is set, the upgrade job runs a full database backup and restore cycle on every helm upgrade, regardless of whether a schema migration is needed. It will not fail if there is nothing to migrate, but it will perform unnecessary work. Always reset upgrade.enable to false once the upgrade completes.

If you use false when a migration was required, pods will fail to start and the API logs will contain an alembic version mismatch error. Rerun the upgrade with upgrade.enable: true to recover, then reset it to false.

Then run:

helm upgrade {RELEASE_NAME} oci://registry-1.docker.io/kasmweb/kasm-helm \
--version 1.1190.0 -n {NAMESPACE} -f my-values.yaml

Next Steps