Skip to content

fix(appimage): unbreak Linux launch on modern GPUs / glibc#2052

Merged
senamakel merged 4 commits into
tinyhumansai:mainfrom
mechmyday:appimage-modern-mesa
May 19, 2026
Merged

fix(appimage): unbreak Linux launch on modern GPUs / glibc#2052
senamakel merged 4 commits into
tinyhumansai:mainfrom
mechmyday:appimage-modern-mesa

Conversation

@mechmyday
Copy link
Copy Markdown
Contributor

@mechmyday mechmyday commented May 18, 2026

Summary

  • Strip host graphics libraries (Mesa / libdrm / libva / libgbm / dri-related libxcb) from the AppImage bundle so the user's system drivers are used at launch instead of the older copies sharun/lib4bin ldd-walks into shared/lib/.
  • Bump the Linux build runner from ubuntu-22.04 to ubuntu-24.04 so the bundled glibc baseline is 2.39 (up from 2.35), which is required for the stripped host graphics libs on current distros (libdrm/libEGL on Ubuntu 24.04 need GLIBC_2.38).
  • Re-sign the AppImage and rebuild its .AppImage.tar.gz updater bundle after stripping, so Tauri's updater signature still validates.

Problem

AppImages produced by CI failed to launch on systems with newer GPUs (RDNA3, Intel Arc, Lovelace) and on newer distros generally.

Two compounding issues:

  1. Stale Mesa in the bundle. lib4bin/quick-sharun ldd-walks every dependency of the Tauri binary and copies the resolved .so files into AppDir/shared/lib/. On the ubuntu-22.04 runner that captures Mesa 22.x, libdrm 2.4.113, etc. — old enough that they cannot initialize newer GPUs. Because shared/lib/ is first on LD_LIBRARY_PATH, the bundled-but-broken drivers shadow the user's working host drivers and CEF crashes during GPU init. AppImage convention is to never ship graphics drivers — they must come from the host (see pkg2appimage excludelist).

  2. glibc layer cake. Even with Mesa stripped, the AppImage built on ubuntu-22.04 bundles libc.so.6 from glibc 2.35. The host's libdrm.so.2 / libEGL.so.1 on modern distros require GLIBC_2.38. Sharun puts the bundled libc first on LD_LIBRARY_PATH, so the loader resolves host libs against bundled libc and fails immediately:

    shared/lib/libc.so.6: version `GLIBC_2.38' not found
      (required by /usr/lib/x86_64-linux-gnu/libdrm.so.2)
    

Solution

scripts/release/strip-appimage-graphics-libs.sh — post-bundle step run after cargo tauri build:

  1. Extracts each .AppImage, walks the top-level lib roots (shared/lib, usr/lib, lib, plus their x86_64-linux-gnu/ siblings — -maxdepth 1 only, so CEF's own swiftshader/ subdir is untouched).
  2. Removes graphics-stack .so files matching the AppImage excludelist convention: libGL*, libGLES*, libGLdispatch, libEGL, libgbm, libdrm*, libva*, libvdpau, libxcb-{dri,glx,present}.
  3. Repacks via appimagetool.
  4. Re-signs the .AppImage and rebuilds .AppImage.tar.gz + its .sig so the Tauri updater pipeline still works.

.github/workflows/build-desktop.yml — wires the strip step into the Linux job and bumps the runner from ubuntu-22.04 to ubuntu-24.04. Comment for the strip step explains why the bundled drivers cannot stay even on a current Ubuntu runner.

Trade-off on the runner bump: glibc 2.39 means AppImage users need glibc 2.39+ (Ubuntu 24.04+, Debian 13+, Fedora 40+, RHEL 10+). Ubuntu 22.04 / Debian 12 users would need an older AppImage. This matches modern AppImage publishing practice — building on the oldest still-supported Ubuntu LTS that covers the actual user base.

Submission Checklist

  • N/A: behaviour-only CI/packaging change — no application logic, no unit-testable code paths. Verified end-to-end by building the AppImage on the bumped runner and launching it on glibc 2.39 host with a modern GPU.
  • N/A: see above — no Vitest / cargo test surface.
  • N/A: behaviour-only change — no feature rows.
  • N/A — no feature IDs.
  • No new external network deps.
  • N/A: not a release-cut UX flow.
  • Linked issue closed via Closes #NNN in the ## Related section

Impact

  • Linux desktop only. Other platforms unaffected — matrix and steps gated on matrix.settings.platform == 'ubuntu-24.04'.
  • glibc baseline raised from 2.35 to 2.39 — drops AppImage support on Ubuntu 22.04, Debian 12, RHEL 9 baseline systems. .deb artifacts are unaffected (the matrix entry produces both deb and appimage; users on older systems can install via deb).
  • AppImage signature/updater unchanged from a consumer's perspective — re-signing happens before upload, signatures still validate.
  • Bundle size very slightly smaller (a few MB of stripped drivers).

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Keep this section for AI-authored PRs. For human-only PRs, mark each field N/A.

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: mechmyday:appimage-modern-mesa
  • Commit SHA: 933ee48

Test Evidence

  • Fork CI run (Linux-only matrix): https://github.com/mechmyday/openhuman/actions/runs/26012988374
  • Local launch on Ubuntu 24.04 (glibc 2.39) + AMD RDNA2 host: CEF boots, JSON-RPC serving, Socket.io client connects. Prior ubuntu-22.04 build crashed at startup with libc.so.6: version 'GLIBC_2.38' not found (required by /usr/lib/x86_64-linux-gnu/libdrm.so.2).

Summary by CodeRabbit

Chores

  • Updated desktop build environment to use Ubuntu 24.04, ensuring compatibility with current system libraries and dependencies
  • Optimized AppImage releases by removing redundant bundled graphics libraries, reducing bundle size

Review Change Stack

mechmyday added 2 commits May 17, 2026 23:25
lib4bin's ldd-walk on the ubuntu-22.04 build runner copies the host's
Mesa/libdrm/libva/libgbm into the AppImage. Those drivers must come
from the user's host system — the runner's Mesa 22.x can't initialize
newer GPUs (RDNA3, Intel Arc, Lovelace) and crashes CEF on launch
because the bundled libs shadow the host's working ones via
LD_LIBRARY_PATH.

Add a post-bundle workflow step that extracts each .AppImage, prunes
the AppImage excludelist graphics-lib patterns from top-level lib dirs
only (CEF's swiftshader subdir is left intact), repacks via
appimagetool, and re-signs both the .AppImage and the updater
tarball when TAURI_SIGNING_PRIVATE_KEY is set.
ubuntu-22.04 bundles glibc 2.35, which is too old for libdrm/libEGL
on modern host distros (those need GLIBC_2.38). After the strip step
removes the bundled Mesa stack, the host's libdrm loads but cannot
resolve against the bundled libc — launch fails immediately with:

  shared/lib/libc.so.6: version `GLIBC_2.38' not found
    (required by /usr/lib/x86_64-linux-gnu/libdrm.so.2)

Bumping the runner to ubuntu-24.04 raises the bundled glibc to 2.39
and matches the symbol set most current distros' graphics drivers
were built against. Comment for the strip step updated; behavior of
the strip script itself is unchanged.
@mechmyday mechmyday requested a review from a team May 18, 2026 06:27
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

📝 Walkthrough

Walkthrough

The pull request upgrades the Linux desktop build pipeline from Ubuntu 22.04 to 24.04 and introduces automated stripping of bundled host graphics libraries from generated AppImage artifacts. A new Bash utility discovers and removes matching graphics driver libraries from AppImage bundles, optionally re-signs modified artifacts and updater tarballs using Tauri signing infrastructure.

Changes

AppImage graphics library stripping and workflow integration

Layer / File(s) Summary
AppImage graphics library stripping script
scripts/release/strip-appimage-graphics-libs.sh
New Bash utility that removes bundled host graphics libraries (libGL, libEGL, libdrm, libva, etc.) from AppImage squashfs-root directories, repacks modified images using appimagetool, and optionally re-signs artifacts and updater tarballs if TAURI_SIGNING_PRIVATE_KEY is provided. Auto-downloads appimagetool to /tmp if not in PATH.
Desktop build workflow Ubuntu 24.04 upgrade
.github/workflows/build-desktop.yml
Linux build matrix updated to ubuntu-24.04; platform-gated steps for Tauri dependency installation and library dump diagnostics adjusted to target the new runner; new "Strip host graphics libs from AppImage" step added to invoke the graphics stripping script against both bundle and output bundle directories using signing secrets.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Poem

🐰 A hop, a script, a careful sweep,
AppImages stripped of drivers deep,
Ubuntu twenty-four takes the stage,
Binaries slimmed to run on every page,
Signed and packed — release's new leap.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary change: fixing AppImage launch issues on modern GPUs and glibc by removing bundled graphics libraries and upgrading to Ubuntu 24.04.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/build-desktop.yml:
- Around line 494-495: The workflow sets TAURI_SIGNING_PRIVATE_KEY to fall back
to UPDATER_PRIVATE_KEY but TAURI_SIGNING_PRIVATE_KEY_PASSWORD does not fall
back, which can break re-signing; update the TAURI_SIGNING_PRIVATE_KEY_PASSWORD
assignment to mirror the private key fallback by using the OR fallback to
UPDATER_PRIVATE_KEY_PASSWORD (i.e., use the secrets expression that falls back
to secrets.UPDATER_PRIVATE_KEY_PASSWORD) so both key and password have the same
fallback behavior (refer to TAURI_SIGNING_PRIVATE_KEY,
TAURI_SIGNING_PRIVATE_KEY_PASSWORD, and UPDATER_PRIVATE_KEY_PASSWORD).

In `@scripts/release/strip-appimage-graphics-libs.sh`:
- Around line 47-58: Update ensure_appimagetool to pin and verify the
appimagetool binary: change APPIMAGETOOL_URL default to a specific release tag
(e.g., replace "continuous" with a version like "13") while still allowing
override via the APPIMAGETOOL_URL env var, download to the existing local
variable tool (/tmp/appimagetool.AppImage), compute and verify the expected
SHA256 (read expected digest from an env var such as APPIMAGETOOL_SHA256) before
running chmod +x, and fail with a clear error if the checksum does not match;
keep the existing command-v check and assignment to APPIMAGETOOL_BIN in
ensure_appimagetool.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6257da42-aba3-49a3-871e-02e0ebd7ee2b

📥 Commits

Reviewing files that changed from the base of the PR and between 0f616e4 and 933ee48.

📒 Files selected for processing (2)
  • .github/workflows/build-desktop.yml
  • scripts/release/strip-appimage-graphics-libs.sh

Comment thread .github/workflows/build-desktop.yml Outdated
Comment on lines +47 to +58
APPIMAGETOOL_URL="${APPIMAGETOOL_URL:-https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage}"

ensure_appimagetool() {
if command -v appimagetool >/dev/null 2>&1; then
APPIMAGETOOL_BIN="$(command -v appimagetool)"
return
fi
local tool=/tmp/appimagetool.AppImage
if [ ! -x "$tool" ]; then
echo "[strip-libs] Downloading appimagetool from $APPIMAGETOOL_URL"
curl -fsSL "$APPIMAGETOOL_URL" -o "$tool"
chmod +x "$tool"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

# First, verify the file exists and examine the relevant lines
if [ -f "scripts/release/strip-appimage-graphics-libs.sh" ]; then
  echo "=== File exists, showing lines 40-65 for context ==="
  cat -n "scripts/release/strip-appimage-graphics-libs.sh" | sed -n '40,65p'
else
  echo "File not found at scripts/release/strip-appimage-graphics-libs.sh"
  # Try to find it
  fd "strip-appimage-graphics-libs.sh"
fi

Repository: tinyhumansai/openhuman

Length of output: 988


🏁 Script executed:

# Check where appimagetool is actually invoked/executed
echo "=== Full script to see execution context ==="
cat -n "scripts/release/strip-appimage-graphics-libs.sh" | head -100

echo -e "\n=== Searching for APPIMAGETOOL_BIN usage ==="
grep -n "APPIMAGETOOL_BIN" "scripts/release/strip-appimage-graphics-libs.sh"

echo -e "\n=== Searching for appimagetool execution ==="
grep -n "appimagetool" "scripts/release/strip-appimage-graphics-libs.sh"

Repository: tinyhumansai/openhuman

Length of output: 4605


🏁 Script executed:

# Get more context around where APPIMAGETOOL_BIN is executed
echo "=== Context around line 121 (execution) ==="
cat -n "scripts/release/strip-appimage-graphics-libs.sh" | sed -n '115,135p'

echo -e "\n=== Where ensure_appimagetool is called (line 151) ==="
cat -n "scripts/release/strip-appimage-graphics-libs.sh" | sed -n '145,160p'

echo -e "\n=== Check if script has any signature/integrity verification elsewhere ==="
grep -i "sha256\|checksum\|sign\|verify" "scripts/release/strip-appimage-graphics-libs.sh"

Repository: tinyhumansai/openhuman

Length of output: 2061


Pin and verify appimagetool before executing it.

Line 47 uses the mutable continuous asset and lines 57–58 execute it immediately without integrity verification. This weakens CI reproducibility and introduces supply-chain risk.

Suggested fix:

  • Replace continuous with a specific version tag (e.g., 13)
  • Add SHA256 verification before chmod +x
  • Use environment variable override for CI/secrets management
Suggested hardening
-APPIMAGETOOL_URL="${APPIMAGETOOL_URL:-https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage}"
+APPIMAGETOOL_URL="${APPIMAGETOOL_URL:-https://github.com/AppImage/appimagetool/releases/download/13/appimagetool-x86_64.AppImage}"
+# Set this in CI/secrets and rotate intentionally when bumping APPIMAGETOOL_URL.
+APPIMAGETOOL_SHA256="${APPIMAGETOOL_SHA256:-}"

 ensure_appimagetool() {
@@
   if [ ! -x "$tool" ]; then
     echo "[strip-libs] Downloading appimagetool from $APPIMAGETOOL_URL"
     curl -fsSL "$APPIMAGETOOL_URL" -o "$tool"
+    if [ -n "$APPIMAGETOOL_SHA256" ]; then
+      echo "${APPIMAGETOOL_SHA256}  ${tool}" | sha256sum -c -
+    fi
     chmod +x "$tool"
   fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/release/strip-appimage-graphics-libs.sh` around lines 47 - 58, Update
ensure_appimagetool to pin and verify the appimagetool binary: change
APPIMAGETOOL_URL default to a specific release tag (e.g., replace "continuous"
with a version like "13") while still allowing override via the APPIMAGETOOL_URL
env var, download to the existing local variable tool
(/tmp/appimagetool.AppImage), compute and verify the expected SHA256 (read
expected digest from an env var such as APPIMAGETOOL_SHA256) before running
chmod +x, and fail with a clear error if the checksum does not match; keep the
existing command-v check and assignment to APPIMAGETOOL_BIN in
ensure_appimagetool.

@senamakel senamakel self-assigned this May 19, 2026
- TAURI_SIGNING_PRIVATE_KEY_PASSWORD now falls back to UPDATER_PRIVATE_KEY_PASSWORD,
  matching the existing key fallback so re-signing works when only the updater
  keypair is configured (CodeRabbit on build-desktop.yml:495).
- Pin appimagetool download to release tag 1.9.0 (was `continuous`) and verify
  SHA256 when APPIMAGETOOL_SHA256 is set, refusing to execute on mismatch.
  Improves CI reproducibility and removes supply-chain risk from running a
  mutable upstream binary unverified (CodeRabbit on strip-appimage-graphics-libs.sh:47).
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/release/strip-appimage-graphics-libs.sh (1)

62-77: 💤 Low value

Consider re-verifying SHA256 even when binary is cached.

When /tmp/appimagetool.AppImage already exists (e.g., persistent CI runners, local dev), the SHA256 check at lines 65-71 is bypassed entirely. If APPIMAGETOOL_SHA256 is rotated without clearing the cache, a stale binary continues to be used without verification.

For GitHub Actions this is low risk since /tmp is fresh per job, but for defense-in-depth:

♻️ Suggested enhancement to verify cached binary
   local tool=/tmp/appimagetool.AppImage
-  if [ ! -x "$tool" ]; then
+  local need_download=0
+  if [ ! -x "$tool" ]; then
+    need_download=1
+  elif [ -n "$APPIMAGETOOL_SHA256" ]; then
+    # Re-verify cached binary matches expected hash
+    if ! echo "${APPIMAGETOOL_SHA256}  ${tool}" | sha256sum -c - >/dev/null 2>&1; then
+      echo "[strip-libs] Cached appimagetool hash mismatch — re-downloading"
+      rm -f "$tool"
+      need_download=1
+    fi
+  fi
+  if [ "$need_download" -eq 1 ]; then
     echo "[strip-libs] Downloading appimagetool from $APPIMAGETOOL_URL"
     curl -fsSL "$APPIMAGETOOL_URL" -o "$tool"
     if [ -n "$APPIMAGETOOL_SHA256" ]; then
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/release/strip-appimage-graphics-libs.sh` around lines 62 - 77, The
script currently skips the APPIMAGETOOL_SHA256 check when the cached binary
($tool) is already present/executable; update the logic so that whenever
APPIMAGETOOL_SHA256 is set the script verifies the checksum of $tool (even if it
already exists), and if the check fails remove $tool and attempt to re-download
(or exit with error if re-download fails). Specifically, change the block around
the existence check for $tool to: (1) if $tool exists and APPIMAGETOOL_SHA256 is
set, run the sha256sum -c check against "${tool}"; (2) on mismatch, rm -f
"$tool" and proceed to the download/code-path that writes and verifies the file;
(3) preserve the existing warning path when APPIMAGETOOL_SHA256 is unset; ensure
APPIMAGETOOL_BIN is still set to "$tool" after successful verification.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@scripts/release/strip-appimage-graphics-libs.sh`:
- Around line 62-77: The script currently skips the APPIMAGETOOL_SHA256 check
when the cached binary ($tool) is already present/executable; update the logic
so that whenever APPIMAGETOOL_SHA256 is set the script verifies the checksum of
$tool (even if it already exists), and if the check fails remove $tool and
attempt to re-download (or exit with error if re-download fails). Specifically,
change the block around the existence check for $tool to: (1) if $tool exists
and APPIMAGETOOL_SHA256 is set, run the sha256sum -c check against "${tool}";
(2) on mismatch, rm -f "$tool" and proceed to the download/code-path that writes
and verifies the file; (3) preserve the existing warning path when
APPIMAGETOOL_SHA256 is unset; ensure APPIMAGETOOL_BIN is still set to "$tool"
after successful verification.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 53fda93d-aa88-47aa-934e-abf069c85549

📥 Commits

Reviewing files that changed from the base of the PR and between 933ee48 and 1e8f920.

📒 Files selected for processing (2)
  • .github/workflows/build-desktop.yml
  • scripts/release/strip-appimage-graphics-libs.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/build-desktop.yml

@senamakel senamakel merged commit ba38e72 into tinyhumansai:main May 19, 2026
24 of 26 checks passed
AusAgentSmith pushed a commit to AusAgentSmith/openhuman that referenced this pull request May 23, 2026
…sai#2052)

Co-authored-by: mechmyday <mechmyday@fogninja.com>
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AppImage 0.53.43 crashes on Linux with EGL_BAD_ATTRIBUTE (Mesa 26.0, Wayland, AMD GPU)

2 participants