Add Nix build system for development - #610
Conversation
|
Hi Fausto, thanks for this nice contrib! I've never used Nix before, but people use to say very good things about this project (both distro and pkg manager). I see you did not change "helper/octopihelper.cpp" in your PR. By the way, I was curious to know which feature you were trying to implement :-) |
I saw other hard-coded paths. I think they may need to be updated for things to work with Nix. Maybe the full functionality (as you suggest) is not working properly when building with Nix. I will try more things later today and report back! If there are incremental changes that can be upstreamed more slowly (e.g. using the standard paths helpers) maybe those are good contributions, too? |
|
Hi @fnune I merged most of your updates to make qt-sudo path agnostic. Thanks! |
This PR adds Nix flake support so contributors can build and run Octopi in an isolated, reproducible dev shell without installing dependencies system-wide. Most of the original PR (aarnt#610) was already merged upstream: the findExecutable() helper, the ctn_OCTOPISUDO -> ctn_QTSUDO rename, and the call-site updates in main.cpp / cachecleaner / notifier / repoeditor / wmhelper. This refresh adds the remaining Nix-related bits and a small set of code changes needed to make a development build (from build/, not /usr/bin/) actually usable end-to-end, including transactions. What is included ---------------- Flake / build: - flake.nix: dev shell with Qt6, CMake, vala, alpm, qtermwidget, KF6 StatusNotifierItem, pipewire, and source builds of alpm_octopi_utils and qt-sudo (v2.4.0). The shellHook puts a small per-shell dir of symlinks (sudo, pacman, fakeroot, pacman-conf) pointing at /usr/bin ahead of the nix paths, so the host's setuid sudo and the host's pacman/libalpm version drive runtime behaviour while nixpkgs supplies the build-time toolchain and libalpm headers. - flake.lock: pinned inputs. - .gitignore: ignore the nix `result` symlink. - README.md: documents `nix develop` for local development. Code: - src/unixcommand.cpp: re-add the OCTOPI_ALLOWED_PATHS env-var branch in isOctoToolRunning() so the four entry points (octopi, octopi-notifier, octopi-cachecleaner, octopi-repoeditor) can run from a build directory. The default for /usr/bin installs is unchanged. - src/unixcommand.{cpp,h}: add UnixCommand::getOctopiHelperPath() that prefers a sibling octphelper next to the running binary, falling back to ctn_OCTOPI_HELPER_PATH. Update the four call sites (helper invocations, terminal helper invocation, helper-existence checks in main.cpp / notifier/main.cpp / cachecleaner/main.cpp). - src/unixcommand.cpp: update isOctopiHelperRunning() to recognise the helper via getOctopiHelperPath() rather than the hardcoded /usr/lib/octopi/octphelper string, so the TCP handshake between octopi and the helper succeeds in a dev build too. - helper/octopihelper.cpp::isProcessRunningFromPath(): widen the trust check from "starts with /usr/bin" to also accept callers co-located with the helper itself, provided the helper's own directory is not group- or world-writable. The threat model is the same as today's check (path-based trust, integrity coming from filesystem permissions); the only difference is that a helper at /usr/lib/octopi/ trusts /usr/bin/octopi as it did before, while a helper at <repo>/build/ trusts <repo>/build/octopi. Distro installs are unaffected. Quick start ----------- git clone https://github.com/aarnt/octopi cd octopi nix develop mkdir -p build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j$(nproc) ./octopi Optional: use direnv (`echo 'use flake' > .envrc`). All existing build methods (qmake, CMake, PKGBUILD) continue to work unchanged.
This PR adds Nix flake support so contributors can build and run Octopi in an isolated, reproducible dev shell without installing dependencies system-wide. Most of the original PR (aarnt#610) was already merged upstream: the findExecutable() helper, the ctn_OCTOPISUDO -> ctn_QTSUDO rename, and the call-site updates in main.cpp / cachecleaner / notifier / repoeditor / wmhelper. This refresh adds the remaining Nix-related bits and a small set of code changes needed to make a development build (from build/, not /usr/bin/) actually usable end-to-end, including transactions. What is included ---------------- Flake / build: - flake.nix: dev shell with Qt6, CMake, vala, alpm, qtermwidget, KF6 StatusNotifierItem, pipewire, and source builds of alpm_octopi_utils and qt-sudo (v2.4.0). The shellHook puts a small per-shell dir of symlinks (sudo, pacman, fakeroot, pacman-conf) pointing at /usr/bin ahead of the nix paths, so the host's setuid sudo and the host's pacman/libalpm version drive runtime behaviour while nixpkgs supplies the build-time toolchain and libalpm headers. - flake.lock: pinned inputs. - .gitignore: ignore the nix `result` symlink. - README.md: documents `nix develop` for local development. Code: - src/unixcommand.cpp: re-add the OCTOPI_ALLOWED_PATHS env-var branch in isOctoToolRunning() so the four entry points (octopi, octopi-notifier, octopi-cachecleaner, octopi-repoeditor) can run from a build directory. The default for /usr/bin installs is unchanged. - src/unixcommand.{cpp,h}: add UnixCommand::getOctopiHelperPath() that prefers a sibling octphelper next to the running binary, falling back to ctn_OCTOPI_HELPER_PATH. Update the four call sites (helper invocations, terminal helper invocation, helper-existence checks in main.cpp / notifier/main.cpp / cachecleaner/main.cpp). - src/unixcommand.cpp: update isOctopiHelperRunning() to recognise the helper via getOctopiHelperPath() rather than the hardcoded /usr/lib/octopi/octphelper string, so the TCP handshake between octopi and the helper succeeds in a dev build too. - helper/octopihelper.cpp::isProcessRunningFromPath(): widen the trust check from "starts with /usr/bin" to also accept callers co-located with the helper itself, provided the helper's own directory is not group- or world-writable. The threat model is the same as today's check (path-based trust, integrity coming from filesystem permissions); the only difference is that a helper at /usr/lib/octopi/ trusts /usr/bin/octopi as it did before, while a helper at <repo>/build/ trusts <repo>/build/octopi. Distro installs are unaffected. Quick start ----------- git clone https://github.com/aarnt/octopi cd octopi nix develop mkdir -p build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j$(nproc) ./octopi Optional: use direnv (`echo 'use flake' > .envrc`). All existing build methods (qmake, CMake, PKGBUILD) continue to work unchanged.
|
@aarnt I rebuilt the PR and worked on it until I was able to run the important stuff from the Nix-built binary:
One caveat: the Nix build builds against a Nix-bundled I'm not sure if that makes the whole concept less appealing to you. But anyway, here's the PR. Of course, take it or leave it! :) |

Refreshed against current
master. Most of the original PR is already upstream, thanks for picking that up. What's left is the Nix-specific stuff plus the small extras needed to make a build frombuild/work end to end (including install / upgrade / remove). Distro installs are untouched.This PR adds Nix flake support to enable clean, isolated development without installing dependencies system-wide.
Screencast_20251116_134654.webm
Motivation
Building Octopi currently requires manually cloning and installing
alpm_octopi_utils,qt-sudo, Qt6 libraries, vala, and other tools system-wide. This makes it difficult to test changes without replacing your system installation of Octopi, pollutes the system with development dependencies, etc. The flake provides isolated, reproducible builds with all dependencies managed automatically in a dev shell with Qt6, CMake, vala, and friends. It buildsalpm_octopi_utilsandqt-sudofrom source and sets up the env so you can build with CMake or qmake just like the existing instructions.Quick start
Optional:
echo 'use flake' > .envrcfor direnv.Code changes
These are the minimum needed to let an Octopi running from
build/work end to end without changing anything for/usr/bin/octopi.src/unixcommand.cpp::isOctoToolRunning(): accept allowed paths from anOCTOPI_ALLOWED_PATHSenv var. The dev shell sets it to/usr/bin:<repo>/build. If unset, the original/usr/bin/<tool>check is used unchanged.src/unixcommand.{cpp,h}::getOctopiHelperPath(): prefer a siblingoctphelpernext to the running binary, fall back toctn_OCTOPI_HELPER_PATH. For a distro install the fallback wins bit for bit (no/usr/bin/octphelperexists). For a dev build the sibling exists. Updates the helper-existence checks inmain.cpp,notifier/main.cpp,cachecleaner/main.cpp, the qt-sudo invocations insrc/unixcommand.cpp, the in-terminal helper command insrc/terminal.cpp, and the TCP handshake recognition inisOctopiHelperRunning().helper/octopihelper.cpp::isProcessRunningFromPath(): widen the trusted path set from "starts with/usr/bin" to also accept callers co-located with the helper itself, provided the helper's directory is not group- or world-writable. Same path-based trust the existing check already uses (integrity from filesystem permissions on the trusted dir). Distro install trusted dir is/usr/lib/octopi/, owned by root, no change. Dev build trusted dir is the build dir, owned by the user who is already typing their qt-sudo password to invoke the helper, so no new escalation primitive.No env vars are passed to the helper, no sudoers tweaks required.
All existing build methods (
qmake,CMake,PKGBUILD) continue to work unchanged.What I tested
On Arch (CachyOS, pacman 7.1.0 / libalpm 16.0.1), with the system
octopi0.19.0-1 package installed in parallel.Inside
nix developfrombuild/:cmake .. -DCMAKE_BUILD_TYPE=Release && make -j$(nproc)producesoctopi,octopi-notifier,octopi-cachecleaner,octopi-repoeditor,octphelper../build/octopilaunches.htopfrom the UI succeeds./usr/lib/octopi/octphelper.logshowsPath of PID ... is <repo>/build/octopiandExec as root: /usr/bin/pacman -S --noconfirm ... htop.htopfrom the UI succeeds (same log pattern,pacman -R).Negative case:
env -u OCTOPI_ALLOWED_PATHS ./build/octopishows the existingYou must use "/usr/bin/octopi" to run Octopipopup and exits 251. Gate unchanged when the env var is not set.Distro install path:
/usr/bin/octopi(system package) still launches and performs transactions normally, without readingOCTOPI_ALLOWED_PATHSand withgetOctopiHelperPath()falling through to/usr/lib/octopi/octphelper.git statusafternix buildis clean (result/is gitignored).