fix(appimage): unbreak Linux launch on modern GPUs / glibc#2052
Conversation
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.
📝 WalkthroughWalkthroughThe 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. ChangesAppImage graphics library stripping and workflow integration
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ 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. Comment |
There was a problem hiding this comment.
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
📒 Files selected for processing (2)
.github/workflows/build-desktop.ymlscripts/release/strip-appimage-graphics-libs.sh
| 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" |
There was a problem hiding this comment.
🧩 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"
fiRepository: 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
continuouswith 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.
- 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).
There was a problem hiding this comment.
🧹 Nitpick comments (1)
scripts/release/strip-appimage-graphics-libs.sh (1)
62-77: 💤 Low valueConsider re-verifying SHA256 even when binary is cached.
When
/tmp/appimagetool.AppImagealready exists (e.g., persistent CI runners, local dev), the SHA256 check at lines 65-71 is bypassed entirely. IfAPPIMAGETOOL_SHA256is 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
📒 Files selected for processing (2)
.github/workflows/build-desktop.ymlscripts/release/strip-appimage-graphics-libs.sh
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/build-desktop.yml
…sai#2052) Co-authored-by: mechmyday <mechmyday@fogninja.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
Summary
shared/lib/.ubuntu-22.04toubuntu-24.04so 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 needGLIBC_2.38)..AppImage.tar.gzupdater 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:
Stale Mesa in the bundle.
lib4bin/quick-sharunldd-walks every dependency of the Tauri binary and copies the resolved.sofiles intoAppDir/shared/lib/. On theubuntu-22.04runner that captures Mesa 22.x, libdrm 2.4.113, etc. — old enough that they cannot initialize newer GPUs. Becauseshared/lib/is first onLD_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).glibc layer cake. Even with Mesa stripped, the AppImage built on ubuntu-22.04 bundles
libc.so.6from glibc 2.35. The host'slibdrm.so.2/libEGL.so.1on modern distros requireGLIBC_2.38. Sharun puts the bundled libc first onLD_LIBRARY_PATH, so the loader resolves host libs against bundled libc and fails immediately:Solution
scripts/release/strip-appimage-graphics-libs.sh— post-bundle step run aftercargo tauri build:.AppImage, walks the top-level lib roots (shared/lib,usr/lib,lib, plus theirx86_64-linux-gnu/siblings —-maxdepth 1only, so CEF's ownswiftshader/subdir is untouched)..sofiles matching the AppImage excludelist convention:libGL*,libGLES*,libGLdispatch,libEGL,libgbm,libdrm*,libva*,libvdpau,libxcb-{dri,glx,present}.appimagetool..AppImageand rebuilds.AppImage.tar.gz+ its.sigso the Tauri updater pipeline still works..github/workflows/build-desktop.yml— wires the strip step into the Linux job and bumps the runner fromubuntu-22.04toubuntu-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
Closes #NNNin the## RelatedsectionImpact
matrix.settings.platform == 'ubuntu-24.04'..debartifacts are unaffected (the matrix entry produces bothdebandappimage; users on older systems can install via deb).Related
AI Authored PR Metadata (required for Codex/Linear PRs)
Linear Issue
Commit & Branch
Test Evidence
ubuntu-22.04build crashed at startup withlibc.so.6: version 'GLIBC_2.38' not found (required by /usr/lib/x86_64-linux-gnu/libdrm.so.2).Summary by CodeRabbit
Chores