Skip to content

Add experimental Alpine x86_64 host packaging - #1452

Open
lbotinelly wants to merge 3 commits into
ilysenko:mainfrom
lbotinelly:feat/alpine-host-runtime
Open

Add experimental Alpine x86_64 host packaging#1452
lbotinelly wants to merge 3 commits into
ilysenko:mainfrom
lbotinelly:feat/alpine-host-runtime

Conversation

@lbotinelly

@lbotinelly lbotinelly commented Sep 9, 2026

Copy link
Copy Markdown

Alpine's musl host cannot load the official glibc desktop runtime, and a desktop running inside another distribution would not exercise repositories against Alpine's own toolchain. This adds an opt-in, rootless packaging path that runs ChatGPT Community directly on Alpine with private glibc libraries while commands continue to use the host shell and repositories.

The packaging reuses the existing signed OpenAI installer and Nix ELF inventory/fixup/audit helpers. Debian runtime metadata and packages are signature/hash verified; only extracted library/shared-data directories enter the output. Per-object RUNPATH and NODEFLIB prevent incompatible fallback into Alpine's libraries. app.asar remains unchanged, upstream native modules are not rebuilt, and Chromium sandboxing is not disabled. Native Alpine build tools and procps are prepared separately. No existing package format or core launcher is changed.

Validation on Alpine 3.24.1 x86_64, KDE Plasma 6.6.6 with XWayland, upstream 26.903.61454:

  • Built from the signed stable OpenAI repository; passed ELF dependency audit and ASAR identity check.
  • Launched the desktop UI twice, with the existing account and local app-server; installed the Community application-menu launcher.
  • Verified packaged Node → bundled Codex app-server → command/exec sees the same Alpine OS, musl shell, repository, and host command paths.
  • Ran Cargo workspace metadata in a host repository. Follow-up validation confirms the standalone command/exec probe is read-only; see the explicit limitation below.
  • Passed 55 direct-host tests: 23 new Alpine Node regression tests, 24 existing ELF/interpreter helper tests, and 8 runtime-downloader tests; JavaScript syntax checks and git diff --check also pass.

This is explicitly experimental/manual packaging: amd64 and XWayland only, no automatic updater. Hardware acceleration, voice/audio, native Wayland, and full browser/computer-use workflows are unvalidated. The upstream process sampler can still select BusyBox ps despite the native helper and log warnings; tested desktop/Git/command workflows work. The container-based cross-distro CI suite was not run locally. Reproduction steps and limits are documented in packaging/alpine/README.md.

Regression coverage and installer hardening (da55d5c)

Three regression tests reproduced partial installations before the fix: an existing desktop entry, a dangling desktop symlink, and an existing launcher all left newly created helpers behind.

  • Validate all install destinations before writes, including dangling symlinks.
  • Publish complete launcher/menu files using same-filesystem, no-clobber hard links, with the menu entry last.
  • Roll back caught failures using recorded file identities, preserving pre-existing and replaced files. Remove only owned files and empty directories; report incomplete cleanup. No power-loss or uncaught-signal recovery guarantee.
  • Correct Desktop Entry string/Exec escaping and icon backslashes; preserve shell argument/URI forwarding.
  • Add 16 installer tests covering conflicts, partial writes, publish failures, retry, concurrent replacements, path validation/quoting, and host PATH/library-environment behavior.
  • Add 7 build tests using tiny compiled ELF fixtures and real copying/patchelf operations: relative symlink targets, per-DSO RUNPATH/NODEFLIB, transitive dependencies, private interpreter, unchanged ASAR/static/static-PIE/musl payloads, and fail-closed build markers. Fixture tests substitute the official inventory contract and dependency-loader execution; they do not replace the real bundle audit.
  • Wire the Alpine Node/Python suites into the existing x86_64 Linux CI job. This CI addition is not an Alpine GUI test.

Reproduced directly on Alpine, without containers:

python3 -B -m unittest discover -s packaging/alpine -p 'test_*.py'
node --test packaging/alpine/*.test.cjs scripts/ci/elf-runtime.test.js scripts/ci/relocate-elf-interpreter.test.js
node --check packaging/alpine/build.cjs
node --check packaging/alpine/install-desktop.cjs
git diff --check

The installed packaged Node → bundled app-server → Alpine shell/repository identity probe and a read-only git diff --check also pass. Trying to run the Node fixture suites through standalone command/exec failed: temporary-file creation returned EROFS and Node child-process creation returned EPERM in its default read-only sandbox. No sandbox permissions were relaxed. The guide now uses a read-only example and explicitly separates direct-host test success from writable app-server validation.

The user reports connections working during normal use. This is not a connection-recovery or long-duration stability test. The running desktop/profile were not changed by this follow-up, and no new full application build was needed: production ELF packaging behavior is unchanged; the builder only gains a testable export. Cross-distro/container, sustained GUI, power-loss, and writable app-server test coverage remain unverified.

@ilysenko ilysenko left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for documenting the Alpine experiment and its limitations. Two blockers remain:

  1. P1 — Restrict the entire imported key set to pinned keys (packaging/alpine/fetch-runtime.py:96-102). Only the first fingerprint is checked, but the complete downloaded blob is dearmored into the trusted keyring. A response containing the expected public key followed by an unpinned attacker key passes this check; gpgv can then trust metadata signed by that additional key. Reject unexpected primary keys (while correctly handling legitimate subkeys), or export only explicitly pinned keys into the verification keyring. Add a regression covering a valid pinned key plus an appended untrusted key; the existing wrong-first-fingerprint mock does not cover this.

  2. P2 — Keep this unproven distro-specific experiment local (packaging/alpine/README.md:1-13, README.md:62-64). The demonstrated scope is one Alpine x86_64 desktop setup, while this adds permanent ownership of a Debian dependency resolver/key lifecycle and another ELF/runtime support matrix, without an Alpine CI build or updater integration. Under CONTRIBUTING's distro-specific ownership rule and the project's maintenance gate, keep this prototype under linux-features/local/alpine-host/ with its own feature.json and README rather than adding a public repository packaging target. A later repository proposal needs demonstrated reusable demand and an agreed support/validation contract. Reusing Nix helpers is useful but does not remove the new runtime-provider burden.

Both concerns are introduced by this PR; existing package formats are not being asked to change.

Before requesting maintainer re-review, run the complete updated base-to-head diff through your own code-review model, fix every blocker it finds, rerun the review, and repeat until that model reports no remaining blockers.

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.

2 participants