Skip to content

Add Nix build system for development - #610

Open
fnune wants to merge 1 commit into
aarnt:masterfrom
fnune:nix-build-system
Open

Add Nix build system for development#610
fnune wants to merge 1 commit into
aarnt:masterfrom
fnune:nix-build-system

Conversation

@fnune

@fnune fnune commented Nov 16, 2025

Copy link
Copy Markdown

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 from build/ 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 builds alpm_octopi_utils and qt-sudo from source and sets up the env so you can build with CMake or qmake just like the existing instructions.

Quick start

# Install Nix if needed
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install

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: echo 'use flake' > .envrc for 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.

  1. src/unixcommand.cpp::isOctoToolRunning(): accept allowed paths from an OCTOPI_ALLOWED_PATHS env var. The dev shell sets it to /usr/bin:<repo>/build. If unset, the original /usr/bin/<tool> check is used unchanged.

  2. src/unixcommand.{cpp,h}::getOctopiHelperPath(): prefer a sibling octphelper next to the running binary, fall back to ctn_OCTOPI_HELPER_PATH. For a distro install the fallback wins bit for bit (no /usr/bin/octphelper exists). For a dev build the sibling exists. Updates the helper-existence checks in main.cpp, notifier/main.cpp, cachecleaner/main.cpp, the qt-sudo invocations in src/unixcommand.cpp, the in-terminal helper command in src/terminal.cpp, and the TCP handshake recognition in isOctopiHelperRunning().

  3. 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 octopi 0.19.0-1 package installed in parallel.

Inside nix develop from build/:

  • cmake .. -DCMAKE_BUILD_TYPE=Release && make -j$(nproc) produces octopi, octopi-notifier, octopi-cachecleaner, octopi-repoeditor, octphelper.
  • ./build/octopi launches.
  • "Check updates" (Ctrl+K) prompts via qt-sudo and reports outdated packages correctly.
  • Installing htop from the UI succeeds. /usr/lib/octopi/octphelper.log shows Path of PID ... is <repo>/build/octopi and Exec as root: /usr/bin/pacman -S --noconfirm ... htop.
  • Removing htop from the UI succeeds (same log pattern, pacman -R).
  • System upgrade from the UI runs to completion.

Negative case:

  • env -u OCTOPI_ALLOWED_PATHS ./build/octopi shows the existing You must use "/usr/bin/octopi" to run Octopi popup 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 reading OCTOPI_ALLOWED_PATHS and with getOctopiHelperPath() falling through to /usr/lib/octopi/octphelper.

git status after nix build is clean (result/ is gitignored).

@aarnt

aarnt commented Nov 16, 2025

Copy link
Copy Markdown
Owner

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.
Did you try upgrading, installing or removing a package with the executables installed in "/path/to/your/build" ? I think helper will veto the transaction. Take a look at "bool OctopiHelper::isProcessRunningFromPath(pid_t pid)" method from "octopihelper.cpp".

By the way, I was curious to know which feature you were trying to implement :-)

@fnune

fnune commented Nov 16, 2025

Copy link
Copy Markdown
Author

By the way, I was curious to know which feature you were trying to implement :-)

This was my feature idea: showing a highlight if something within "news" is related to a package you have installed.

image

However, I realized that the data for news is not structured enough to be able to get a package name reliably. E.g. sometimes the message just says "Plasma 6.5 desktop" :/

@fnune

fnune commented Nov 16, 2025

Copy link
Copy Markdown
Author

I see you did not change "helper/octopihelper.cpp" in your PR. Did you try upgrading, installing or removing a package with the executables installed in "/path/to/your/build" ? I think helper will veto the transaction. Take a look at "bool OctopiHelper::isProcessRunningFromPath(pid_t pid)" method from "octopihelper.cpp".

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?

@aarnt

aarnt commented Nov 24, 2025

Copy link
Copy Markdown
Owner

Hi @fnune

I merged most of your updates to make qt-sudo path agnostic.
Did not merge *nix specific code. I'm waiting for your next tests.

Thanks!

@fnune
fnune force-pushed the nix-build-system branch from dfe3dcf to 56ef80f Compare May 22, 2026 10:15
fnune added a commit to fnune/octopi that referenced this pull request May 22, 2026
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.
@fnune
fnune force-pushed the nix-build-system branch from 56ef80f to 5919788 Compare May 22, 2026 10:20
@fnune

fnune commented May 22, 2026

Copy link
Copy Markdown
Author

@aarnt I rebuilt the PR and worked on it until I was able to run the important stuff from the Nix-built binary:

  • System upgrade
  • Installing a package (tried htop)
  • Removing a package

One caveat: the Nix build builds against a Nix-bundled libalpm, but it may differ from the host's version. I would maybe recommend using this for development and not for production builds.

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! :)

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