Skip to content

feat(linux): Linux desktop support — Part 6/6: HTTPS client, self-updater, and setup uninstaller - #44

Merged
thtbee merged 22 commits into
thtbee:mainfrom
jochenkirstaetter:linux-6-updater
Oct 23, 2026
Merged

thtbee merged 22 commits into
thtbee:mainfrom
jochenkirstaetter:linux-6-updater

Conversation

@jochenkirstaetter

Copy link
Copy Markdown
Contributor

Summary

Part 6 of 6 for Linux desktop support (stacked on #43 / linux-5-storage, #42 / linux-4-media, #41 / linux-3-input, and #38 / linux-2-basics).

Adds the Linux HTTPS client, self-updater (.AppImage and .deb), and setup uninstaller:

  • Linux HTTPS Client (desktop/app/src/linux/http.rs):
    • HTTPS-only get, get_retrying, get_json, download, and download_to_file backed by curl (--proto =https --proto-redir =https) with wget (--https-only) fallback.
    • Enforces response byte limits and writes downloaded artifacts with O_NOFOLLOW and 0o600 permissions.
  • Self-Updater (desktop/app/src/updater.rs):
    • Matches Linux .AppImage and .deb release assets (x86_64 and aarch64 / arm64) and verifies SHA-256 digests against SHA256SUMS.txt.
    • Stages downloads in an owner-only (0o700, UID-verified, non-symlink) cache directory (~/.cache/nectarlink/updates).
    • Supports atomic in-place .AppImage replacement and TOCTOU-hardened privileged .deb installation (PRIVILEGED_DEB_INSTALL_SCRIPT copies the package to root-owned 0700 /var/cache/nectarlink-update, re-verifies sha256sum -c as root, and runs dpkg -i).
  • Setup & Uninstaller (desktop/app/src/setup.rs, desktop/app/i18n/):
    • Detects installed .deb (dpkg-query) and /opt/nectarlink installations, cleans up user autostart, shortcuts, send-to entries, and storage bookmarks, and runs elevated package/directory removal.
    • Includes de and zh_CN translations for the new Setup strings (Couldn't uninstall NectarLink: %1 and Uninstall stopped with code %1.).

Verification

  • cargo fmt --all --check
  • cargo xtask tokens --check
  • cargo xtask strings --check
  • cargo clippy --locked -p nectarlink-protocol -p nectarlink-core -p nectarlink-ffi -p nectarlink-cli -p xtask --all-targets -- -D warnings
  • cargo test --locked -p nectarlink-protocol -p nectarlink-core -p nectarlink-ffi -p nectarlink-cli -p xtask
  • cargo clippy --locked -p nectarlink-desktop -p nectarlink-vcam -p s1-qt-rust --all-targets -- -D warnings
  • cargo test --locked -p nectarlink-desktop -p nectarlink-vcam (311 + 6 unit tests pass)
  • pwsh ./scripts/check-headers.ps1 (456 files checked, 0 problems)

…uts, network & BLE (Part 2)

Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
…-monitor parser

Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
…ode for watched PIDs

Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
…rdings (Part 4)

Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
@thtbee

thtbee commented Oct 23, 2026

Copy link
Copy Markdown
Owner

Thanks for opening this. Notes for this part are on #38 (comment). The .deb update path is careful (the hash is checked again as root on a root-owned copy), nice. Small things: pkexec sh -c makes the prompt name sh; a tarball install only opens the browser; and reqwest with rustls is already in the dependency tree, which would remove the curl/wget dependency in linux/http.rs.

jochenkirstaetter and others added 8 commits October 23, 2026 14:39
… D-Bus, and packaging

Applies the Part 2 review improvements and fixes from upstream/linux-review-fixes
(b346bfe, 47e3e06, 6291b51, a815275, 0be2ddf, 20c70f3, ccb9318):
- USB ADB: retry another local TCP port only when adb reports a port bind failure (47e3e06)
- Linux platform layer: native D-Bus/Netlink/Qt integrations for clipboard, tray,
  notifications (6291b51), single-instance activation token, BlueZ/NetworkManager,
  Wake-on-LAN, BLE beacon, and clean SIGTERM/SIGINT/SIGHUP shutdown (ccb9318)
- Shell & Doctor: remove Windows settings links/explorer.exe shims (20c70f3) and
  provide plain Linux Doctor readiness checks and wording with German and Chinese
  translations (a815275)
- Release workflow & packaging: pin AppImage tools with SHA-256 verification and
  smoke-test every Linux package (.deb, AppImage, tarball) with --version (0be2ddf)

Many thanks to @thtbee for the thorough review and reference implementation on
linux-review-fixes!

Co-authored-by: Bee <302257494+thtbee@users.noreply.github.com>
Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
…and window capture

Merges updated linux-2-basics and applies the Part 3 review improvements from
upstream/linux-review-fixes (b346bfe, 7bc9b2b, a815275):
- Keyboard layout resolution (7bc9b2b): add desktop/app/src/linux/keymap.rs using
  libxkbcommon / libxkbcommon-x11 to resolve keysyms and keycodes against the
  user's active X11 or Wayland keyboard layout for text typing and shortcuts
- Input injection & window capture (b346bfe): native XTest/uinput/RemoteDesktop
  portal input handling and X11/Portal window capture improvements
- DeckPage QML & i18n (a815275): use Linux shortcut labels (Super+D, Screenshot,
  Super) with German and Chinese translations

Many thanks to @thtbee for the collaborative review and reference implementation
on linux-review-fixes!

Co-authored-by: Bee <302257494+thtbee@users.noreply.github.com>
Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
… portal, and OpenH264 ABI

Applies the Part 4 review improvements and fixes from upstream/linux-review-fixes (b346bfe, c41f185, 20c70f3):
- Wayland ScreenCast portal: open the portal's PipeWire remote connection via OpenPipeWireRemote and pass it as fd 3 to gst-launch-1.0 pipewiresrc, with session restore_token persistence (c41f185)
- Media & audio: PipeWire/PulseAudio speaker monitor capture, MPRIS D-Bus client & server, FFmpeg 8 libavcodec compatibility, v4l2loopback virtual camera, and virtual microphone
- OpenH264 ABI compatibility: auto-detect 40-byte (Debian/Ubuntu libopenh264.so.7 2.4.1) vs 56-byte (upstream 2.3+ r_psnr) SLayerBSInfo layout at runtime and install libopenh264-dev in Linux CI

Many thanks to @thtbee for the thorough review and reference implementation on linux-review-fixes!

Co-authored-by: Bee <302257494+thtbee@users.noreply.github.com>
Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
…phone storage

Applies the Part 5 review improvements and fixes from upstream/linux-review-fixes (b346bfe, e58ee10):
- Replace whole-phone sync folder with an on-demand /dev/fuse filesystem mount via fusermount3/fusermount
- Add GTK3 and XBEL file-manager bookmark integration and clean unmount on disconnect or shutdown
- Only advertise STORAGE_MOUNT / STORAGE_READ / STORAGE_WRITE on Linux when /dev/fuse and fusermount are available (e58ee10)

Many thanks to @thtbee for the thorough review and reference implementation on linux-review-fixes!

Co-authored-by: Bee <302257494+thtbee@users.noreply.github.com>
Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
Merge linux-5-storage and incorporate @thtbee's review fixes from
linux-review-fixes (b346bfe..e58ee10) for Part 6 (HTTP, setup, updater):
- Enforce 1024-byte response line limit and preserve 120s idle read
  timeout in HTTP redirect/chunked readers
- Guard privileged .deb and .tar.gz installs in setup/updater against
  command injection and TOCTOU races
- Fix #[cfg] platform coverage in setup.rs and updater.rs so macOS
  builds and tests compile cleanly alongside Windows and Linux

Co-authored-by: Bee <302257494+thtbee@users.noreply.github.com>
Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
@jochenkirstaetter

Copy link
Copy Markdown
Contributor Author

Updated with linux-5-storage and integrated @thtbee's Part 6 review fixes from linux-review-fixes (e58ee10 — HTTP response line bounds & preserved 120s idle read timeout, plus hardened .deb/.tar.gz setup and update flows), along with #[cfg] platform coverage in setup.rs and updater.rs for macOS CI. Huge thanks @thtbee for the collaborative effort!

@jochenkirstaetter

Copy link
Copy Markdown
Contributor Author

Hi @thtbee

The failing CI for macOS has been noted, going to fix it.

Cheers

Co-authored-by: Bee <302257494+thtbee@users.noreply.github.com>
Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
…euid on Unix

setup::install and setup::remove ran the NSIS installer's switches
(/S /PROGRESS, uninstall.exe) on macOS too once they became
cfg(not(target_os = "linux")); they are Windows-only again, and macOS
gets its own: there is no installer to run, and removing clears this
user's data. The Linux install no longer hands those switches to a file
that is neither a .deb nor a tarball.

updater::current_euid read the owner of /proc/self, which doesn't exist
on macOS and so read as root; it uses geteuid now.
@thtbee

thtbee commented Oct 23, 2026

Copy link
Copy Markdown
Owner

I pushed one small fix on top (fdef5c2), since it was quicker than describing it. With setup::install and setup::remove moved to cfg(not(target_os = "linux")), macOS compiled the NSIS installer path (/S /PROGRESS, uninstall.exe); they're Windows-only again, and macOS has its own (no installer to run; removing clears this user's data). The Linux install no longer passes those switches to a file that's neither a .deb nor a tarball. And current_euid() read the owner of /proc/self, which doesn't exist on macOS and so came back as root; it uses libc::geteuid() now. Windows clippy is clean; CI will cover Linux and macOS. Thanks again for taking in all the review fixes so quickly.

@thtbee

thtbee commented Oct 23, 2026

Copy link
Copy Markdown
Owner

Sorry, my earlier commit broke the macOS clippy job: the crate denies unsafe_code unless it's allowed locally, and progress_file became unused off Windows. 7b789dd adds #[allow(unsafe_code)] on current_euid (as window_capture.rs does) and the same cfg_attr(not(windows), allow(dead_code)) that run_tracked already has. Clippy is clean on Linux and Windows; macOS should follow in CI.

@thtbee thtbee 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.

Reviewed on the final branch along with the rest of the series: all findings addressed, the macOS stubs now build, and all nine checks pass on 7b789dd. Thank you, Jochen.

@thtbee
thtbee merged commit efe780e into thtbee:main Oct 23, 2026
9 checks passed
@jochenkirstaetter
jochenkirstaetter deleted the linux-6-updater branch October 24, 2026 00:40
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