Migrate Claude Desktop to Anthropic's official APT repo (fixes the coder-xfce-vnc build) #19

Merged
GuillaumeHemmen merged 1 commit from 0-migrate-official-claude-desktop into master 2026-07-24 06:12:16 +00:00
Member

Why the build is red

The coder-xfce-vnc build has failed on every branch since 2026-07-22, including master. The cause is not in this repo.

Anthropic released an official Claude Desktop for Linux beta and took the claude-desktop package name with it. The community claude-desktop-debian repack this image used therefore renamed itself to claude-desktop-unofficial, leaving claude-desktop behind as a 624-byte transitional dummy that merely depends on the new name.

So apt-get install claude-desktop still succeeded — it pulled the dummy — and the very next assertion failed:

test -x /usr/bin/claude-desktop

test prints nothing on failure, which is exactly why the CI log ends with no error text at all:

Setting up claude-desktop (1.16000.0-1) ...
error building image: error building stage: failed to execute command: waiting for process to exit: exit status 1

Every path the block asserted (/usr/bin/claude-desktop, claude-desktop.desktop, /usr/lib/claude-desktop/) moved to a -unofficial name.

Why migrate rather than chase the rename

The rename is the migration signal — the community project stepped aside because Anthropic now ships this officially.

Both repos package the same upstream Electron app, and the official repo is at the same version the community repack wraps (1.24012.0), with an identical Depends: list. So this is a supply-chain change, not a functional one: same app, signed by Anthropic, one fewer third-party repo and keyring.

What the switch required

  • The deb symlinks /usr/bin/claude-desktop straight to the bundled Electron binary. The community repack shipped a shell launcher there that did its own environment setup; nothing does that now. The wrapper is consequently the only place ELECTRON_DISABLE_SANDBOX=1 and --disable-dev-shm-usage get applied. The deb's setuid-root chrome-sandbox helper and AppArmor userns profile don't help in an unprivileged pod — allowPrivilegeEscalation=false makes setuid a no-op, and loading AppArmor policy needs privileges the pod lacks.
  • The desktop entry is com.anthropic.Claude.desktop, and its Exec is the bare, PATH-resolved claude-desktop rather than an absolute path. The wrapper in /usr/local/bin therefore shadows every launch path on its own — which also makes the wrapper's absolute /usr/bin target load-bearing rather than stylistic: an unqualified call there would re-resolve to the wrapper on PATH and recurse forever. The entry also carries NewChat/NewCode actions, so the sed rewrites all three Exec lines and those launcher actions get the pod flags too.
  • The published signing-key fingerprint is now asserted before the key is trusted, so a substituted key fails the build instead of silently arming a rogue repo with root-level package installs.
  • coder-init-desktop.sh's stale-entry healer now checks all three entry names a long-lived PVC can carry (claude-desktop.desktop, claude-desktop-unofficial.desktop, com.anthropic.Claude.desktop) and matches only absolute-path Execs, so Anthropic's own bare Exec=claude-desktop — which already resolves to the wrapper — is correctly left alone.

Verification

The RUN step was extracted from the Dockerfile verbatim and executed in an ubuntu:24.04 pod on the cluster:

Check Result
Signing-key fingerprint 31DD…CACE pass
apt-get install claude-desktop pass, postinst clean
test -x "$(readlink -f /usr/bin/claude-desktop)" pass → /usr/lib/claude-desktop/claude-desktop
grep -q '^Exec=/usr/local/bin/claude-desktop' pass
grep -q '^Categories=Development;' pass
Installed version 1.24012.0

The healer regex was unit-tested against 10 cases (5 bypass forms that must be parked, 5 wrapper-routed/custom forms that must be left alone) — all correct. shellcheck is clean on both modified scripts.

Not verified: rendering inside the VNC session, which needs a real desktop. It's the same Electron build as the package already in use, so ELECTRON_DISABLE_SANDBOX=1 should behave identically — but that is inference, not proof. Worth a smoke test once the image lands.

Note for other branches

master is red for this same reason, so this should land before rebasing anything else. #18 is unaffected on its own merits — it just inherited the failure.

Beta caveats inherited from upstream: no Computer Use, no dictation, Debian-based distros only.

## Why the build is red The `coder-xfce-vnc` build has failed on every branch since **2026-07-22**, including `master`. The cause is not in this repo. Anthropic released an [official Claude Desktop for Linux beta](https://code.claude.com/docs/en/desktop-linux) and took the `claude-desktop` package name with it. The community [claude-desktop-debian](https://github.com/aaddrick/claude-desktop-debian) repack this image used therefore renamed itself to `claude-desktop-unofficial`, leaving `claude-desktop` behind as a 624-byte transitional dummy that merely depends on the new name. So `apt-get install claude-desktop` still *succeeded* — it pulled the dummy — and the very next assertion failed: ``` test -x /usr/bin/claude-desktop ``` `test` prints nothing on failure, which is exactly why the CI log ends with no error text at all: ``` Setting up claude-desktop (1.16000.0-1) ... error building image: error building stage: failed to execute command: waiting for process to exit: exit status 1 ``` Every path the block asserted (`/usr/bin/claude-desktop`, `claude-desktop.desktop`, `/usr/lib/claude-desktop/`) moved to a `-unofficial` name. ## Why migrate rather than chase the rename The rename *is* the migration signal — the community project stepped aside because Anthropic now ships this officially. Both repos package the same upstream Electron app, and the official repo is at **the same version the community repack wraps** (`1.24012.0`), with an identical `Depends:` list. So this is a supply-chain change, not a functional one: same app, signed by Anthropic, one fewer third-party repo and keyring. ## What the switch required - **The deb symlinks `/usr/bin/claude-desktop` straight to the bundled Electron binary.** The community repack shipped a *shell launcher* there that did its own environment setup; nothing does that now. The wrapper is consequently the only place `ELECTRON_DISABLE_SANDBOX=1` and `--disable-dev-shm-usage` get applied. The deb's setuid-root `chrome-sandbox` helper and AppArmor userns profile don't help in an unprivileged pod — `allowPrivilegeEscalation=false` makes setuid a no-op, and loading AppArmor policy needs privileges the pod lacks. - **The desktop entry is `com.anthropic.Claude.desktop`, and its `Exec` is the bare, PATH-resolved `claude-desktop`** rather than an absolute path. The wrapper in `/usr/local/bin` therefore shadows every launch path on its own — which also makes the wrapper's absolute `/usr/bin` target *load-bearing rather than stylistic*: an unqualified call there would re-resolve to the wrapper on `PATH` and recurse forever. The entry also carries `NewChat`/`NewCode` actions, so the `sed` rewrites all three `Exec` lines and those launcher actions get the pod flags too. - **The published signing-key fingerprint is now asserted before the key is trusted**, so a substituted key fails the build instead of silently arming a rogue repo with root-level package installs. - **`coder-init-desktop.sh`'s stale-entry healer** now checks all three entry names a long-lived PVC can carry (`claude-desktop.desktop`, `claude-desktop-unofficial.desktop`, `com.anthropic.Claude.desktop`) and matches only absolute-path `Exec`s, so Anthropic's own bare `Exec=claude-desktop` — which already resolves to the wrapper — is correctly left alone. ## Verification The `RUN` step was extracted from the Dockerfile **verbatim** and executed in an `ubuntu:24.04` pod on the cluster: | Check | Result | |---|---| | Signing-key fingerprint `31DD…CACE` | pass | | `apt-get install claude-desktop` | pass, postinst clean | | `test -x "$(readlink -f /usr/bin/claude-desktop)"` | pass → `/usr/lib/claude-desktop/claude-desktop` | | `grep -q '^Exec=/usr/local/bin/claude-desktop'` | pass | | `grep -q '^Categories=Development;'` | pass | | Installed version | **1.24012.0** | The healer regex was unit-tested against 10 cases (5 bypass forms that must be parked, 5 wrapper-routed/custom forms that must be left alone) — all correct. `shellcheck` is clean on both modified scripts. **Not verified:** rendering inside the VNC session, which needs a real desktop. It's the same Electron build as the package already in use, so `ELECTRON_DISABLE_SANDBOX=1` should behave identically — but that is inference, not proof. Worth a smoke test once the image lands. ## Note for other branches `master` is red for this same reason, so this should land before rebasing anything else. #18 is unaffected on its own merits — it just inherited the failure. Beta caveats inherited from upstream: no Computer Use, no dictation, Debian-based distros only.
#0 - Migrate Claude Desktop to Anthropic's official APT repo (fixes the build)
All checks were successful
/ docker-dev-ci (push) Successful in 3m46s
/ docker-dev-coder (push) Successful in 4m18s
/ docker-dev-coder-xfce-vnc (push) Successful in 11m59s
de216dc06a
The coder-xfce-vnc build has been failing since 2026-07-22. The cause is not
in this repo: Anthropic released an official Claude Desktop for Linux beta and
took the `claude-desktop` package name with it, so the community
claude-desktop-debian repack the image used renamed itself to
`claude-desktop-unofficial` and left `claude-desktop` behind as a 624-byte
transitional dummy.

`apt-get install claude-desktop` therefore still succeeded — it pulled the
dummy — and the very next assertion, `test -x /usr/bin/claude-desktop`, failed
against a package that ships none of those paths. `test` prints nothing, which
is why the CI log ends at "Setting up claude-desktop (1.16000.0-1) ..."
followed by a bare "exit status 1" with no error text.

Rather than chase the rename, switch to the official package. Both repos
package the same upstream Electron app at the same version (1.24012.0), so
this is a supply-chain change, not a functional one: same app, signed by
Anthropic, one less third-party repo.

Adjustments the switch requires:

- The deb symlinks /usr/bin/claude-desktop straight to the bundled Electron
  binary; the community repack shipped a shell launcher there that did its own
  environment setup. Nothing does that now, so the wrapper is the only place
  ELECTRON_DISABLE_SANDBOX and --disable-dev-shm-usage get applied. The deb's
  setuid chrome-sandbox helper and AppArmor userns profile don't help in an
  unprivileged pod (allowPrivilegeEscalation=false makes setuid a no-op, and
  loading AppArmor policy needs privileges the pod lacks).
- The desktop entry is com.anthropic.Claude.desktop, and its Exec is the bare,
  PATH-resolved `claude-desktop` rather than an absolute path. The wrapper in
  /usr/local/bin consequently shadows every launch path on its own, which also
  makes the wrapper's absolute /usr/bin target load-bearing rather than
  stylistic: an unqualified call would re-resolve to the wrapper and recurse.
  The entry also carries NewChat/NewCode actions, so the sed rewrites all three
  Exec lines and those actions get the pod flags too.
- The published signing-key fingerprint is now asserted before the key is
  trusted, so a substituted key fails the build instead of arming a rogue repo
  with root-level package installs.
- coder-init-desktop.sh's stale-entry healer now checks all three entry names a
  long-lived PVC can carry, and matches only absolute-path Execs so Anthropic's
  own bare `Exec=claude-desktop` is correctly left alone.

Verified by running the extracted RUN step verbatim in an ubuntu:24.04 pod:
fingerprint check, install, binary resolution, and both entry assertions all
pass, installing 1.24012.0. Not verified: rendering inside the VNC session,
which needs a real desktop — worth a smoke test once the image lands.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GuillaumeHemmen deleted branch 0-migrate-official-claude-desktop 2026-07-24 06:12:16 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
actions/sindri!19
No description provided.