Repository navigation
fix(platforms): Keep OnDemand's tokens in the job, fix Coder's installs, and end what a session daemonizes - #421
Merged
Merged
Conversation
…ay from proxies The job provisioned the session token with curl -H and -d, which put the master token and the session token on a command line any account on the compute node can read through ps while the request runs; with the master token, any of them could replace the token table. A node whose environment names an http_proxy also handed both tokens to that proxy. curl now reads the URL, headers, and body from its standard input and sends the request to the node itself, bypassing any proxy. Reproduced on main: the job, rendered by ood_core's basic template with the dashboard's staged paths and run as a scheduler runs it, ran one provisioning curl whose arguments held the master token and the session token, and a logging proxy named in http_proxy received the POST to /api/tokens with both. Verified on this commit through the same path: the only provisioning curl is `curl -fsS -o /dev/null --config -`, no process of the job carries either token on its command line, the proxy receives nothing, and the session token still authenticates the WebSocket as controller. Only the provisioning request changes. Its JSON body has no spaces, so curl's unquoted config form takes it as is.
…er than its rate-limited API The module read the latest tag from api.github.com, whose unauthenticated limit of 60 requests an hour is shared by everything behind one address, so workspaces behind one NAT used it up and the install then had no version to download. It now reads the tag from the releases/latest redirect of the web page, which has no such limit. Reproduced on main with Coder 2.37.3 from a host whose unauthenticated quota was used up: the API answered 403 "API rate limit exceeded", the workspace's script log began with "curl: (22) The requested URL returned error: 403", Selkies was never installed, and the agent ended in start_error. Verified from the same host with the quota still at 0: the redirect resolved 2.0.0, and the workspace installed it and turned healthy in 45 seconds. Only an empty selkies_version reaches this; four lines replace two.
The packages workflow names the Debian packages after the flavor, as the images do (selkies-<version>-debiantrixie-amd64.deb), and docs/native.md derives that name from os-release, while the module still asked for selkies-<version>-trixie-amd64.deb, which the next release does not publish. The name is now ID and VERSION_CODENAME on Debian, as it is ID and VERSION_ID on Ubuntu; 2.0.0 carries its Debian packages under both names. Reproduced on main: in debian:bookworm and debian:trixie the module derives bookworm-amd64.deb and trixie-amd64.deb, while main's packages.yaml and deb.sh produce debianbookworm-amd64.deb and debiantrixie-amd64.deb. Verified on this commit: the same images derive the flavor's names, which 2.0.0 serves, ubuntu:24.04 and ubuntu:26.04 derive the names they did before, and a Coder workspace on Debian 13 installed selkies-2.0.0-debiantrixie-amd64.deb through the module. One line.
The package depends on the PulseAudio client library alone, and selkies-session starts only a sound server the workspace has, so a workspace the module installed Selkies into streamed without audio. The install step now adds the distribution's PulseAudio where neither pulseaudio nor pipewire-pulse is installed; a workspace that already has Selkies and Xvfb still installs nothing. Reproduced on main with Coder 2.37.3 on codercom/example-desktop (Ubuntu 26.04, XFCE): the session log read "no sound server came up; the session has no audio" and Selkies started with audio off. Verified on this commit in the same workspace: PulseAudio installs, "pulseaudio serves the session's audio", Selkies starts with audio on, and the desktop streams at 60 frames a second through Coder's path app. The package resolves under every package manager the module installs with: apt on Ubuntu 24.04 and 26.04 and Debian 12 and 13, dnf on Fedora 44 and AlmaLinux 9, apk on Alpine 3.22, and pacman on Arch, where it conflicts with pipewire-pulse, which the check finds first. One command in the install block, run only where it already installs.
pip install 'selkies[jupyter]' gives a Jupyter server the Selkies launcher item and the page loads, but the pixelflux wheel takes libgbm, libpixman, and libxkbcommon from the system, as a desktop carries them. On a host without them the capture extension fails to import and the page shows no picture, and the page describing the Jupyter integration named no host requirement. Reproduced with selkies 2.0.0 from PyPI in a clean python:3.12 image with Xvfb, xterm, and PulseAudio: JupyterLab's Selkies card opened /selkies/ in a new tab, Firefox 156 and WebKit 26.6 received no video in 90 seconds, and the log read "pixelflux library unavailable (libxkbcommon.so.0: cannot open shared object file ...)". With libgbm1, libpixman-1-0, and libxkbcommon0 added, the same card streams the desktop at 62 frames a second in Chrome 154, Firefox 156, and WebKit 26.6, and a Jupyter server killed outright takes its session and its runtime directory with it. Documentation only; the list links pixelflux's own rather than copying its distribution names beyond Debian and Ubuntu.
…its environment ends with it selkies-session found what a desktop daemonizes out of its process groups by the runtime directory in each process's environment, which an agent that makes itself undumpable hides. XFCE's ssh-agent does, so each session left one running under the host's init, with its socket directory in /tmp, wherever nothing else reaps the session: Coder, Jupyter, or a scheduler that tracks no cgroup. The launcher now makes itself the child subreaper of everything the session orphans, finds those orphans by their parent, sends them SIGTERM with the process groups before SIGKILL, and collects them once they exit. The session's own children stay with their Popen, which keeps Selkies' exit status. Reproduced on main with the integration suite's stand-in desktop, given an agent that daemonizes and makes itself undumpable as ssh-agent does: it survived SIGTERM in all five blocks that run the stand-in (X11, PulseAudio past a failing PipeWire, stock Xvfb, Wayland, detached), and in the PipeWire block the launcher held two uncollected zombies, the servers it had killed. In a real XFCE session on Debian 13 under Selkies 2.0.0's package, XFCE's ssh-agent ran under PID 1 and outlived the session, its socket directory with it. Verified on this commit: the suite passes 74 of 74 (68, and 6 failures, before), with the agent gone and no zombie under the launcher, including a process the stand-in orphans that exits at once, as a menu's double fork does. The same XFCE session's ssh-agent runs under the launcher and ends with the session, removing its socket directory. The unit tier passes (142), and the Jupyter suite passes 24 of 24 on X11 and Wayland, a killed server still taking the session with it. os.waitid behaves the same on Python 3.9, 3.12, and 3.15. What else changes: the launcher collects exited children every half second, the sweep reads each process's stat beside its environment, and stragglers get SIGTERM before SIGKILL.
This was referenced Sep 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes to the platform integrations from #409, found while taking them upstream: OSC/ood_core#1001, OSC/ondemand#5849, OSC/ood-documentation#1431, coder/registry#1149, coder/coder#30026, and jupyterhub/jupyter-server-proxy#620. Each commit stands on its own and carries its evidence in its message; in short:
fix(ondemand): the session tokens stay in the job. The provisioning request put the master token and the session token on curl's command line, which every account on the compute node can list throughps, and handed both to a proxy the node's environment names. curl now reads them from its standard input and sends the request to the node itself.main: the job, rendered by ood_core's basic template and run as a scheduler runs it, showed both tokens in the provisioning curl's arguments, and a logging proxy named inhttp_proxyreceivedPOST /api/tokenswith both.curl -fsS -o /dev/null --config -, no process of the job carries a token on its command line, the proxy receives nothing, and the session token still authenticates the WebSocket as controller.fix(coder): the latest release comes from GitHub's redirect, not its API. Unauthenticated API calls share 60 requests an hour per address, so workspaces behind one NAT used them up and the install had no version to download.mainwith Coder 2.37.3 from a host whose quota was used up:curl: (22) ... 403, Selkies never installed, and the agent ended instart_error.fix(coder): Debian packages by the names releases now give them. Since bf0e273 the packages workflow names themselkies-<version>-debian<codename>-<arch>.deb, asdocs/native.mdderives them, while the module still asked for<codename>alone, which the next release does not publish. The 2.0.0 release now carries its Debian packages under both names.main:debian:bookwormanddebian:trixiederivebookworm-amd64.debandtrixie-amd64.deb, whilepackages.yamlanddeb.shproducedebianbookworm-amd64.debanddebiantrixie-amd64.deb.selkies-2.0.0-debiantrixie-amd64.deb.fix(coder): PulseAudio where the workspace has no sound server. The package depends on the PulseAudio client alone, andselkies-sessionstarts only a server the workspace has, so a workspace the module installed Selkies into streamed without audio.mainoncodercom/example-desktop(Ubuntu 26.04, XFCE): "no sound server came up; the session has no audio", and Selkies started with audio off.pulseaudioresolves under apt (Ubuntu 24.04 and 26.04, Debian 12 and 13), dnf (Fedora 44, AlmaLinux 9), apk (Alpine 3.22), and pacman (Arch, where it conflicts withpipewire-pulse, which the check finds first).docs: what a Jupyter host brings beside the wheel. pixelflux's wheel takes libgbm, libpixman, and libxkbcommon from the system, as a desktop carries them, and the Jupyter section named no host requirement.python:3.12image with Xvfb, xterm, and PulseAudio: JupyterLab's Selkies card opened/selkies/, Firefox and WebKit received no video in 90 seconds, and the log readpixelflux library unavailable (libxkbcommon.so.0: ...).fix(session): the launcher adopts what the session orphans. XFCE'sssh-agentdaemonizes and makes itself undumpable, so the sweep that finds escaped processes by the runtime directory in their environment could not see it, and each session left one running wherever nothing else reaps the session: Coder, Jupyter, or a scheduler that tracks no cgroup. The launcher is now the child subreaper of everything the session orphans. It ends those orphans with the session, SIGTERM before SIGKILL, and collects them as they exit, leaving its own children to their Popen, which keeps Selkies' exit status.main:test_session_launcher, with a stand-in agent that daemonizes and makes itself undumpable, fails 6 checks: the agent survives in all five stand-in blocks, and the PipeWire-fallback block holds two uncollected zombies. A real XFCE session on Debian 13 leavesssh-agentunder PID 1 with its socket directory.test_jupyter_proxypasses 24 of 24 on X11 and Wayland.What else it can affect. The OnDemand change touches only the provisioning request, and the Coder changes run only where the module installs something. The launcher now collects exited children every half second and reads each process's
statbeside its environment when it stops.pre-commit run --all-filespasses. Not covered: the OnDemand app through a live portal's own dashboard (the same provisioning ran under a portal's Slurm through ood_core's new template, which uses this request), and aarch64.Related. With the Coder agent's
SSH_CONNECTIONin the session's environment, the first connection to a Debian 13 workspace with a sound server aborts Selkies 2.0.0 (free(): invalid size). pcmflux 2.1.0's wheel bundles a second libxcb, which takes over the host copy's own calls once libpulse opens an X connection, as it does only whenSSH_CONNECTIONis set. selkies-project/pcmflux@a85622b leaves libxcb to the host, and a 2.1.0 wheel rebuilt that way streamed the same session with audio. Until a release carries it, the PulseAudio commit here exposes the abort on Debian 13, where such workspaces streamed without audio before.