Skip to main content
Version: v0.2.0

Workspace images

Linux workspaces run OCI images from the waas-images project — Kasm-style, 100% OSS desktop images purpose-built for the platform.

Design in one paragraph

TigerVNC's Xvnc is the display server (no Xvfb double stack): it serves RFB natively — exactly what guacd's VNC client speaks — and supports dynamic resize. RDP is a bridge: xrdp without sesman/PAM, its libvnc backend pointed at the local Xvnc, fully non-root — both protocols always show the same session. Services run under tini + supervisord, entirely unprivileged; the entrypoint renders all mutable config into tmpfs so the root filesystem can be read-only. The web client is guacd/wwt from the platform — no noVNC in the images. Every image boots in CI with --read-only --cap-drop ALL --security-opt no-new-privileges and must pass a real protocol handshake — the hardening checklist is enforced, not aspirational.

VNC is the recommended protocol for Linux; RDP is a compatibility option, and SSH exists only on the OS-level desktop images. Per-app images (apps/*) are VNC-only by construction — xrdp and sshd binaries are simply absent, not merely disabled — and ship as single-app kiosks: they are built on the bare core (no desktop environment in the image at all, Kasm-style), and the WAAS_APP session mode runs the one application undecorated and maximized, with no panel, terminal or window-manager keybindings behind it. The exception is devtools, a real XFCE desktop on the VNC-only XFCE parent.

The contract with the Workspace CR

Any image honoring this contract works as a WaaS Linux workspace — that's the whole interface, whether the image comes from waas-images or your own build:

AspectValue
VNC port5901 (RFB, VncAuth) — the default for os: linux
RDP port3389 (TLS negotiated) — only images built with RDP support, enabled via WAAS_RDP_ENABLED=1
SSH port2222 — publickey only, OS-level desktop images only, opt-in via WAAS_SSH_ENABLED=1
AudioPulseAudio native protocol on 4713, streamed by guacd when the session enables audio
ReadinessTCP open on the template port ⇔ the protocol server accepts connections (matches the operator's probes)
Userwaas_user, UID/GID 1000:1000, home /home/waas_user = the operator's PVC mount; fresh volumes are seeded from /etc/skel
Writable paths/home/waas_user (PVC), /tmp, /run (emptyDirs) — everything else read-only-safe
Required envWAAS_DESKTOP_PASSWORD — one session password shared by VNC and RDP. The image refuses to start without it. Legacy names (VNC_PW, RDP_PASSWORD) are refused with an explicit error.
Optional envWAAS_VNC_RESOLUTION, WAAS_VNC_COL_DEPTH, WAAS_VNC_ENABLED, WAAS_RDP_ENABLED, WAAS_RDP_AUTH_ENABLED, WAAS_SSH_ENABLED, WAAS_SSH_AUTHORIZED_KEYS(_FILE), WAAS_SSH_HOST_KEY_FILE, WAAS_STARTUP (full session command), WAAS_APP (single-app kiosk command — mutually exclusive with WAAS_STARTUP), WAAS_AUDIO_ENABLED, WAAS_TLS_CERT/WAAS_TLS_KEY
Init hookoptional ConfigMap mounted at /etc/waas/init.d/*.sh sourced at boot, as UID 1000
Recommended pod securityContextrunAsNonRoot, runAsUser/fsGroup: 1000, readOnlyRootFilesystem: true, capabilities.drop: [ALL], allowPrivilegeEscalation: false, seccompProfile: RuntimeDefault → PodSecurity restricted compliant

Every runtime variable is WAAS_-prefixed — that is the whole naming contract. Under the platform you rarely set the password yourself: when a template has no explicit credential source, the operator generates a per-workspace password and injects WAAS_DESKTOP_PASSWORD via secretKeyRef on its own (see Credentials).

Security defaults worth knowing:

  • RDP authentication is on by default and has no build-time opt-out — an image can never leave the pipeline with an open RDP.
  • SSH is publickey-only by construction: the unprivileged sshd cannot read /etc/shadow, so password auth is impossible.
  • No secrets are ever baked into layers; the password arrives via env at runtime, is hashed into tmpfs and scrubbed from the environment.
  • -dev tagged variants (e.g. devtools-dev) are a documented reduced profile — sudo baked in, requires a relaxed pod securityContext — meant to be gated behind allowedGroups in the catalog.

Which images exist?

The list of published images is deliberately not duplicated here — it changes with every release. The authoritative, machine-readable list is the catalog the platform itself syncs from: catalog-waas-images.yaml (and catalog-kasmweb.yaml for the optional upstream Kasm images). Roughly: OS desktops (Ubuntu/Debian/Fedora XFCE, multi-protocol) and per-app images (Firefox, Chrome, LibreOffice, VS Code devtools) on amd64 + arm64.

Image tags are immutable (<version>, plus throwaway <version>-g<sha> branch tags); published images are cosign-signed with a CycloneDX SBOM attested to the image reference.

The interesting part is building your own → next page.