cmux-rd host: systemd socket admission for Cloud desktops, plus a Linux release workflow

Merged
TE
1d ago
+1098-85

cmux-rd host gets the production Cloud admission mode. systemd passes the host a root-only Unix socket, and only the machine's root link receiver may connect, after it has admitted the owner with the owner's one-time link token for service desktop. A new release workflow publishes cmux-rd for x86_64 Linux so Cloud images can install it.

Leo, 2026-11-05: "Also go check in on the state of affairs of screen sharing remotely on these machines, like the cloud machines, because there was so much VNC work. But it's also like, I feel like it wasn't really linked up end to end here, and we have an opportunity quite soon to start doing that. [...] And then it became AI computer use!!" Also, on cmux#36080: "is that really necessary? can't you both do it at the same time?", and his standing order: "don't stick it into dev. Put it into prod".

Changelog

none (host and release plumbing; the Cloud desktop becomes visible with the app slice)

What changes

cmux-rd host --listen-systemd --peer-uid N (Linux) (new src/systemd.rs, src/host.rs)

  • The host takes its one listening socket from systemd (LISTEN_FDS=1, LISTEN_PID = self, fd 3). It refuses to start without those, or when the passed fd is not a listening Unix stream socket. It marks the fd close-on-exec and clears LISTEN_*.
  • --peer-uid is required. Each accepted connection's SO_PEERCRED uid must equal it, or the connection is shut down before a byte is read.
  • No TCP or UDP listener in this mode. --token-fd, --bind, --port, --single-tenant-overlay and --upstream-record are refused.
  • The hello token is not checked, because the link already admitted the owner. The principal is the machine owner, a person at the app (--owner, default owner), and the hello's user/class/interactive claims are ignored. The start mode picks view or control. A hello that asks for UDP is refused with StreamCarrierOnly.
  • --xauthority PATH sets XAUTHORITY for the X connections.
  • --idle-exit-s (default 120): with no connection for that long the host exits, and socket activation starts it again.
  • Every other mode works as before. SocketCarrier and serve_viewer are now generic over the stream (TCP or Unix). The TCP path keeps its token check, peer check and UDP carrier.
  • README: a new "Security: Cloud machines (production)" section describes this mode. The phase-1 section is now marked development.

.github/workflows/cmux-rd-release.yml (pattern of cmux-browser-host-release.yml)

  • Triggers: a tag push cmux-rd-v*, or workflow_dispatch with input tag. The tag must match the crate version and sit on feat-cmux-next.
  • Builds cmux-rd for x86_64-unknown-linux-gnu with --no-default-features --features openh264,link (no bench, no x264), through cargo-zigbuild at the glibc 2.31 floor. It checks the glibc symbols and fails if the binary defines any x264/OpenH264 codec symbols. It runs the crate tests first.
  • Publishes cmux-rd-<version>-x86_64-unknown-linux-gnu.tar.gz and checksums.txt (sha256) as prerelease cmux-rd-v<version>, with a build-provenance attestation.
  • The archive holds bin/cmux-rd, LICENSE (GPL-3.0-or-later) and THIRD_PARTY_LICENSES.md. The notices come from scripts/release.py notices, using the build's exact cargo tree through build-support/notices/rust_notices.py. They cover the Rust std, Zig compiler_rt/musl and glibc, and they say that OpenH264 is not in the archive (cmux-rd openh264-install downloads Cisco's binary on the machine). One review choice is local to this binary: openh264-sys2's BSD-2-Clause text in upstream/LICENSE.
  • Runners read the Linux pool. .github/warm-sources.json gets a cold entry.

What ran

  • Fleet Linux (cmux-ci test --setup rust, run 42008007660, SUCCESS):
    • cargo build --locked --release --no-default-features --features openh264,link --bin cmux-rd passed.
    • cargo test --locked (default features): 14 passed, 1 ignored.
    • cargo test --no-default-features --features openh264,link systemd: 7 passed.
  • New tests:
    • Missing LISTEN_FDS/LISTEN_PID refuses.
    • A wrong pid or a count other than 1 refuses.
    • A passed fd that is TCP, unconnected or not a socket refuses.
    • A listening Unix socket is taken and set close-on-exec.
    • A peer uid mismatch closes with nothing sent back.
    • The expected uid is admitted.
    • The idle accept times out.
    • --listen-systemd parses as a value-less flag.
  • release.py notices generated a 65-crate notices file from the release cargo tree, and release.py package wrote the archive layout above.
  • Workflow guards test_ci_linux_single_size, test_ci_overflow_pick_reads_pool and test_ci_warm_sources pass, test_ci_upload_artifact_retention reports nothing for this file, and actionlint is clean.

The systemd units, the receiver's desktop service, the platform capability and the app pane are separate PRs.

Agent session: agent session

🤖 Generated with Claude Code


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Adds the production Cloud admission mode to cmux-rd host: systemd passes a root-only Unix socket, and only the machine's root link receiver may connect, after it admitted the owner with the owner's one-time link token for service desktop. A new release workflow publishes cmux-rd for x86_64 Linux so Cloud images can install it.

Cloud admission (--listen-systemd)

  • The host takes its one listening Unix socket from systemd (LISTEN_FDS/LISTEN_PID, fd 3) and refuses to start without it or when the fd is not a listening Unix stream socket.
  • Each accepted connection's SO_PEERCRED uid must equal --peer-uid; anything else is closed before a byte is read. The check keeps out non-root processes only; the link admission is the real boundary.
  • No TCP or UDP listener: --token-fd, --bind, --port, --single-tenant-overlay, --upstream-record, --browser, and --browser-cdp-port are refused.
  • The hello token and its user/class/interactive claims are ignored: the link already admitted the owner, so the principal is the machine owner (--owner, default owner), and view/control come from the start mode. A hello asking for UDP is refused with StreamCarrierOnly.
  • --xauthority sets XAUTHORITY for the X connections; --idle-exit-s (default 120) makes the host exit when idle so socket activation restarts it.
  • SocketCarrier and serve_viewer are now generic over the stream; the TCP path keeps its token check, peer check, and UDP carrier.

Linux release workflow

  • Runs on a cmux-rd-v* tag (or dispatch), builds x86_64-unknown-linux-gnu with openh264,link (no bench, no x264) at the glibc 2.31 floor, and fails on any x264/OpenH264 codec symbols in the binary or when the symbol table is too empty to check.
  • Publishes cmux-rd-<version>-x86_64-unknown-linux-gnu.tar.gz and checksums.txt as prerelese, with build-provenance attestation; re-runs never replace already-published assets.
  • The archive holds bin/cmux-rd, LICENSE, and THIRD_PARTY_LICENSES.md generated from the build's exact cargo tree; OpenH264 stays a runtime download on the machine, not in the archive.