diff --git a/README.md b/README.md index 59e51fe..b4ae5c6 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ Already have a clone? Just run it directly: Not run by `bootstrap.sh`: -- `coder/desktop/` — Coder template for coder.nic-oconnor.com: an XFCE +- `coder/desktop/` — Coder template for coder.nic-oconnor.com: a KDE Plasma desktop (KasmVNC) pod on the homelab cluster that applies this repo via the dotfiles module. Push with `coder templates push desktop -d coder/desktop`; see its README. diff --git a/coder/desktop/README.md b/coder/desktop/README.md index 3930c74..38ca2f2 100644 --- a/coder/desktop/README.md +++ b/coder/desktop/README.md @@ -1,7 +1,7 @@ # coder/desktop — Coder desktop template -A Coder template for : an XFCE desktop in the -browser (the [KasmVNC module](https://registry.coder.com/modules/coder/kasmvnc)) +A Coder template for : a KDE Plasma desktop in +the browser (the [KasmVNC module](https://registry.coder.com/modules/coder/kasmvnc)) running as a pod on the homelab Kubernetes cluster, set up from this repo by the [dotfiles module](https://registry.coder.com/modules/coder/dotfiles). @@ -15,14 +15,42 @@ coder templates push desktop -d coder/desktop -y The in-cluster provisioner uses the `coder` service account, whose workspace Role is bound in the `coder` namespace — which is where workspaces go. +## The image + +`image/Dockerfile` builds `git.nic-oconnor.com/public/coder-desktop-kde:noble`: +`codercom/enterprise-desktop:ubuntu-noble` plus KDE Plasma (with Dolphin, +Konsole, Kate) and KasmVNC. Both are baked in because only `/home/coder` is +persisted, so installing them at start time would cost minutes on every +start. The package is public on Gitea, so the cluster pulls it without a +secret. Rebuild after changing the Dockerfile: + +```sh +docker build -t git.nic-oconnor.com/public/coder-desktop-kde:noble coder/desktop/image +docker push git.nic-oconnor.com/public/coder-desktop-kde:noble +``` + +The pod pulls with `Always`, so workspaces pick the new image up on their +next start. + +Workarounds the Dockerfile carries: + +- `kwin-x11` is installed explicitly. It is only a Recommends of + `kde-plasma-desktop`, and without it Plasma starts with no window manager. +- `/usr/local/bin/startkde -> startplasma-x11`. KasmVNC's `-select-de kde` + (what the module runs) checks for `startkde`, which Plasma 5.20+ renamed, + and otherwise fails with "Desktop Environment not installed". +- KWin compositing is off in `/etc/xdg/kwinrc`: there is no GPU, and + software compositing over VNC only adds lag. Turn it back on in System + Settings if you want it. + ## What a workspace gets -- `codercom/enterprise-desktop:ubuntu-noble`: XFCE, git, python3, and the - `coder` user (uid 1000) with passwordless sudo. +- The image above, running as the `coder` user (uid 1000) with passwordless + sudo. - A PVC (`truenas-iscsi`, default 30 GiB) at `/home/coder`. Everything the - dotfiles install into `$HOME` survives stops; system packages (zsh, docker - CLI, KasmVNC) are reinstalled on each start because the root filesystem - is not persisted. + dotfiles install into `$HOME` survives stops, and so do the Plasma settings. + System packages the dotfiles add (zsh, the docker CLI) are reinstalled on + each start. - The KasmVNC app, path-based (`subdomain = false`) because the deployment has no wildcard access URL. - A "Dotfiles" startup script: clones this repo into @@ -42,9 +70,9 @@ bootstrap still applies everything else; `secrets`, `mcp-config` and `hermes` are reported as not completed. Fix that later from a workspace terminal with `~/.config/coderv2/dotfiles/secrets/install.sh`, then refresh the dotfiles. -## Why these pins +## Why noble -- `ubuntu-noble`, not `ubuntu`: the `ubuntu` tag is now 26.04 (resolute), and - KasmVNC publishes no resolute package, so the module's install 404s. -- `kasm_version = "1.5.0"`: the newest KasmVNC release, which has a noble - build. Revisit both once KasmVNC ships a resolute `.deb`. +The `enterprise-desktop:ubuntu` tag is now 26.04 (resolute), and KasmVNC +publishes no resolute package. The image is pinned to noble with KasmVNC +1.5.0; revisit once KasmVNC ships a resolute `.deb`, and keep +`kasm_version` in `main.tf` in step with `KASMVNC_VERSION`. diff --git a/coder/desktop/image/Dockerfile b/coder/desktop/image/Dockerfile new file mode 100644 index 0000000..f17a3c9 --- /dev/null +++ b/coder/desktop/image/Dockerfile @@ -0,0 +1,34 @@ +# coder/desktop/image — the workspace image: Coder's desktop base with KDE +# Plasma and KasmVNC baked in, so a start does not spend minutes in apt (the +# root filesystem is not persisted; only /home/coder is). +# +# docker build -t git.nic-oconnor.com/public/coder-desktop-kde:noble coder/desktop/image +# docker push git.nic-oconnor.com/public/coder-desktop-kde:noble +# +# noble, not resolute: KasmVNC publishes no resolute package yet. +FROM codercom/enterprise-desktop:ubuntu-noble + +ARG KASMVNC_VERSION=1.5.0 + +USER root +# kwin-x11 is only a Recommends of kde-plasma-desktop, so --no-install-recommends +# drops it and Plasma comes up with no window manager (no title bars). +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + kde-plasma-desktop kwin-x11 dolphin konsole kate plasma-nm breeze-gtk-theme \ + dbus-x11 libdatetime-perl \ + && curl -fsSL -o /tmp/kasmvnc.deb \ + "https://github.com/kasmtech/KasmVNC/releases/download/v${KASMVNC_VERSION}/kasmvncserver_noble_${KASMVNC_VERSION}_amd64.deb" \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends /tmp/kasmvnc.deb \ + && rm -f /tmp/kasmvnc.deb /home/coder/.xsessionrc \ + && rm -rf /var/lib/apt/lists/* + +# KasmVNC's `-select-de kde` (what the Coder kasmvnc module runs) looks for a +# `startkde` binary, which Plasma 5.20+ renamed to startplasma-x11. +RUN ln -s /usr/bin/startplasma-x11 /usr/local/bin/startkde + +# No GPU in the pod: software compositing over VNC only adds lag. Users can +# still turn it on in System Settings (~/.config/kwinrc overrides this). +RUN printf '[Compositing]\nEnabled=false\n' > /etc/xdg/kwinrc + +USER coder diff --git a/coder/desktop/main.tf b/coder/desktop/main.tf index af5d73b..4763253 100644 --- a/coder/desktop/main.tf +++ b/coder/desktop/main.tf @@ -1,4 +1,4 @@ -# coder/desktop — Coder template: an XFCE desktop in the browser (KasmVNC) +# coder/desktop — Coder template: a KDE Plasma desktop in the browser (KasmVNC) # on the homelab Kubernetes cluster, set up from this dotfiles repo. # # Push it with: coder templates push desktop -d coder/desktop @@ -174,21 +174,14 @@ resource "coder_agent" "main" { arch = data.coder_provisioner.me.arch os = "linux" - # The home PVC hides whatever the image put in /home/coder, so seed it on - # first start: the skel dotfiles, plus the image's .xsessionrc (XFCE session - # env that KasmVNC's X session reads). + # The home PVC hides whatever the image put in /home/coder, so seed it + # with the skel dotfiles on first start. startup_script = <<-EOT set -e if [ ! -f ~/.init_done ]; then cp -rT /etc/skel ~ || true touch ~/.init_done fi - if [ ! -f ~/.xsessionrc ]; then - printf '%s\n' \ - 'export GNOME_SHELL_SESSION_MODE=ubuntu' \ - 'export XDG_CURRENT_DESKTOP=xfce' \ - 'export XDG_SESSION_TYPE=x11' > ~/.xsessionrc - fi EOT env = merge({ @@ -235,9 +228,10 @@ module "dotfiles" { manual_update = true } -# XFCE is in the image; the module installs KasmVNC and serves it on :6800. -# kasm_version: KasmVNC ships a .deb per Ubuntu codename, and the module's -# default (1.4.0) is older than we need; 1.5.0 has noble. +# KDE Plasma and KasmVNC are baked into the image (image/Dockerfile), so the +# module skips its install and just configures and starts KasmVNC on :6800. +# kasm_version: only used if the image lacks KasmVNC; keep it in step with +# KASMVNC_VERSION in the Dockerfile. # subdomain = false: the deployment has no wildcard access URL, so the app # is served path-based under coder.nic-oconnor.com. module "kasmvnc" { @@ -245,7 +239,7 @@ module "kasmvnc" { source = "registry.coder.com/coder/kasmvnc/coder" version = "1.3.0" agent_id = coder_agent.main.id - desktop_environment = "xfce" + desktop_environment = "kde" kasm_version = "1.5.0" subdomain = false } @@ -299,8 +293,9 @@ resource "kubernetes_deployment_v1" "main" { } spec { # Runs as the image's coder user (uid 1000), which has passwordless - # sudo. The KasmVNC module and the dotfiles modules (zsh, docker) - # need it for apt; the namespace enforces PSA baseline, which allows it. + # sudo. The KasmVNC module needs it to write /etc/kasmvnc, and the + # dotfiles modules (zsh, docker) for apt; the namespace enforces PSA + # baseline, which allows it. security_context { run_as_user = 1000 fs_group = 1000 @@ -309,8 +304,8 @@ resource "kubernetes_deployment_v1" "main" { container { name = "dev" - image = "codercom/enterprise-desktop:ubuntu-noble" - image_pull_policy = "IfNotPresent" + image = "git.nic-oconnor.com/public/coder-desktop-kde:noble" + image_pull_policy = "Always" command = ["sh", "-c", coder_agent.main.init_script] env { name = "CODER_AGENT_TOKEN"