mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-26 05:29:45 +00:00
dcdbca28f8
## Summary Unattended updates on small Proxmox LXCs were being OOM-killed. The server installer staged the release archive (~280 MB for v6.5.0) and its extracted tree (~750 MB) under `/tmp`. On Debian 13 and many LXC templates `/tmp` is tmpfs, and tmpfs pages count against the container's memory cgroup. The reporter's host log shows the `/lxc/118` cgroup at its 1 GiB limit with ~820 MB of shmem, the kernel OOM-killing the container's `systemd` (PID 1), and Proxmox then stopping the container. `install.sh` now downloads and extracts into owner-only hidden directories under the install directory: - The install directory is always writable from the hardened `pulse-update.service` sandbox. - The staged binary already lives there. - The disk headroom preflight now measures the filesystem the update actually stages on. The Go updater already prefers its data directory over `/tmp` for the same reason. Two follow-ups that come with staging on disk: - **Stale staging sweep.** An interrupted run's staging (~1 GB) now survives reboots. Staging setup removes stale `.pulse-extract-XXXXXX` and `.pulse-<release>-linux-<arch>-XXXXXX` directories under the install directory. It only removes real directories with those exact names, never symlinks or files, and only when their ctime is more than 6 hours old. `install.sh` has no update lock, so age is what proves no live run still owns them. - **Ownership.** Every recursive `chown -R pulse:pulse "$INSTALL_DIR"` (archive install, source build, `setup_directories`) now goes through `chown_install_dir_for_pulse`, which skips staging. The payload that root still reads is never handed to the service account. The `Failed to print table: Broken pipe` line in the report came from `systemctl list-unit-files | grep -q` in v6.5.0's service discovery. `main` already reads that inventory in full, and it was not the cause of the failure. ## Tests - New Go tests `TestRootInstallScriptSweepsOnlyStaleServerStaging` (fresh staging kept, stale staging removed; look-alike names, files, symlinks and their targets kept) and `TestRootInstallScriptPulseOwnershipExcludesServerStaging` (staging skipped, no raw recursive install-dir chown left). - New `test_archive_extraction_stages_on_the_install_filesystem` (server installer stop harness) and `test_download_stages_archive_on_the_install_filesystem` (temporary inputs harness) fail against the current installer and pass with this change. - `scripts/tests/test_server_installer_stop.py`, `test_server_installer_temporary_inputs.py`, `test_server_service_discovery.py`, and the `TestRootInstall*` tests in `scripts/installtests` pass (run on Linux). Refs #2785