Discord + browserworkspace
The production workspace image used by the kasm-vpn Deployment. It extends kasmweb/discord with CloakBrowser so a single KASM session exposes Discord and a browser side-by-side — the browser is the canonical screen-share target streamed through Discord's video feature.
Self-healing desktop
A custom startup script spawns three supervisor loops that poll every 3–5 seconds via pgrep and relaunch CloakBrowser, Discord, or the nav_shim if they exit — no manual session restart.
- cloak_loop — respawns the bundled Chromium fork.
- discord_loop — respawns the upstream Discord.
- nav_shim_loop — respawns the URL launcher shim.
What it gives you
Features
Discord + browser bundle
One supervised container exposes Discord and a browser side-by-side for in-session screen-share.
Supervisor auto-respawn
Three background loops relaunch any component that exits, keeping the desktop populated after a crash.
Reproducible browser
A known Chromium build gives consistent stream fonts and codecs across sessions.
Owned resource limits
Bundling lets KBVE own requests/limits against one artifact instead of patching a vendor tag.
Guarded URL launcher
The nav_shim exposes only CDP Page.navigate behind bearer auth, a scheme allowlist, and a Cilium NetworkPolicy.
Supervisors
Crash recovery
/dockerstartup/custom_startup.sh spawns three background supervisors:
| Loop | Process matched (pgrep -f) | Action |
|---|---|---|
cloak_loop | cloakbrowser | Relaunches /opt/cloakbrowser/cloakbrowser $CLOAK_APP_ARGS $START_URL |
discord_loop | `discord | electron` |
nav_shim_loop | nav_shim.py | Relaunches python3 /dockerstartup/nav_shim.py |
Each loop polls every 3–5 seconds. Closing the Discord window or the browser window from the desktop triggers a respawn — no manual KASM session restart needed.
The original kasmweb/discord startup script is preserved as
/dockerstartup/discord_startup.sh so its arg-handling, profile setup, and
maximize logic continue to work unchanged.
Desktop shortcuts + helper scripts (v0.0.5)
Section titled “Desktop shortcuts + helper scripts (v0.0.5)”The Desktop ships with launcher icons so the operator does not have to
remember paths. Each .desktop entry is built into the image at
/home/kasm-user/Desktop/ and the underlying scripts live in
/home/kasm-user/scripts/.
| Icon | Action |
|---|---|
| Terminal | Opens xfce4-terminal (the package is now installed) |
| Discord | Direct launcher for /usr/share/discord/Discord (host-update skipped) |
| CloakBrowser | Direct launcher for the bundled Chromium fork |
| Open URL in Browser | zenity prompt → posts to the local nav_shim (falls back to a fresh cloakbrowser --new-window if the shim is down) |
| Reload CloakBrowser | Kills cloakbrowser, clears the Singleton* locks; the supervisor respawns it in ~3s |
| Reset Discord | Stops Discord, clears Cache//Code Cache//GPUCache//Shared Dictionary/, re-seeds SKIP_HOST_UPDATE |
Discord host-update gate
Section titled “Discord host-update gate”scripts/seed-discord-config.sh writes SKIP_HOST_UPDATE: true to
~/.config/discord/settings.json before every Discord launch. The
upstream Discord-on-Linux build otherwise attempts a self-update on each
boot, which fails inside the gluetun-tunneled namespace and leaves the
desktop without a Discord window.
CloakBrowser stability
Section titled “CloakBrowser stability”cloak_loop now passes
--user-data-dir=/home/kasm-user/.config/cloakbrowser --disable-software-rasterizer and clears stale SingletonLock/SingletonSocket
files before each respawn. The loop also tracks an exponential backoff
when the binary exits in under 2 seconds and tails the last few lines of
/tmp/cloakbrowser.log so the failure is visible from kubectl logs.
Configuration
Runtime env
| Variable | Default | Notes |
|---|---|---|
START_URL | https://kbve.com | Launch URL for the cloakbrowser instance |
CLOAK_APP_ARGS | (chromium defaults) | Override the full cloakbrowser arg list |
LAUNCH_DISCORD | 1 | Set to 0 to disable the Discord supervisor |
LAUNCH_CLOAK | 1 | Set to 0 to disable the browser supervisor |
LAUNCH_NAV_SHIM | 1 | Set to 0 to disable the URL launcher shim |
NAV_SHIM_PORT | 9998 | Shim listens on this port (0.0.0.0) |
CDP_PORT | 9222 | Cloakbrowser CDP port (bound to 127.0.0.1) |
URL_LAUNCHER_TOKEN | (k8s secret) | Reuses kasm-vnc-pw value as bearer token |
VNC_PW | (k8s secret) | Provided by the kasm Deployment |
APP_ARGS | (inherited) | Discord-side Electron args, consumed upstream |
Ops
Resources & build
The workspace container in apps/kube/kasm/manifest/deployment.yaml is
sized for Discord + a browser tab + a screenshare encoder running in parallel:
| CPU | Memory | |
|---|---|---|
requests | 2 | 4Gi |
limits | 4 | 8Gi |
The Gluetun sidecar keeps its own modest profile (100m/128Mi request,
500m/384Mi limit) — bumping it does not buy noticeable latency since
the VPN tunnel is bandwidth-, not CPU-bound.
npx nx run kasm-void:containernpx nx run kasm-void:testPublished tags land at ghcr.io/kbve/kasm-void:<version>; the post-publish
chore workflow syncs the Deployment image pin to match version.toml.
Questions
Frequently asked
What is the KASM Void image?
kasm-void is the production workspace image used by the kasm-vpn Deployment. It extends kasmweb/discord with CloakBrowser so the KASM session exposes both Discord and a browser side-by-side, with the browser as the canonical Discord screen-share target.
Why bundle Discord and a browser instead of using the stock image?
The stock kasmweb/discord ships only Discord and leaves an empty desktop when closed. Bundling gives a known reproducible browser binary for consistent stream fonts and codecs and lets KBVE own resource requests and limits against a single artifact.
How does KASM Void keep the desktop populated after a crash?
A custom startup script spawns three supervisor loops (cloak_loop, discord_loop, nav_shim_loop) that poll every 3 to 5 seconds via pgrep and relaunch CloakBrowser, Discord, or the nav_shim if they exit, so no manual KASM session restart is needed.
