Skip to content

nix: add fixed-output package derivation - #13076

Open
Ansh-Sonkusare wants to merge 9 commits into
cheaper-inference:release/v3.8.53from
Ansh-Sonkusare:nix-packaging
Open

Ansh-Sonkusare wants to merge 9 commits into
cheaper-inference:release/v3.8.53from
Ansh-Sonkusare:nix-packaging

Conversation

@Ansh-Sonkusare

@Ansh-Sonkusare Ansh-Sonkusare commented Sep 8, 2026 •

Copy link
Copy Markdown

Summary

  • Adds a flake.nix and nix/omniroute.nix so Nix users can install OmniRoute reproducibly.
  • Uses a fixed-output derivation (FOD) because package-lock.json references workspace packages (@omniroute/browser-pool, open-sse, packages/browser-pool) that npm ci --offline can't resolve inside the Nix sandbox. The FOD runs npm install -g omniroute@<version> with network access and pins reproducibility via outputHash.
  • Adds a short "Nix / NixOS" section to the README.

Closes #13075.

Test plan

  • nix build .#default on x86_64-linux
  • nix run .#default -- --help prints usage
  • Verify the outputHash matches (rebuild after rm -rf ~/.cache/nix — should be a substitute hit or match on fresh build)

Notes

This is an offer, not urgent — happy to move files around (packaging/nix/, subdir naming, README placement) or drop the flake and keep just the callPackage file if you prefer. Version bumps require regenerating outputHash.

🤖 Generated with Claude Code

Add a Nix flake and derivation so Nix/NixOS users can install OmniRoute
with `nix profile install github:diegosouzapw/OmniRoute`.

Uses a fixed-output derivation instead of buildNpmPackage: upstream
package-lock.json references workspace packages (@omniroute/browser-pool,
open-sse, packages/browser-pool) that `npm ci --offline` cannot resolve
inside the Nix build sandbox. The FOD runs `npm install -g omniroute@<v>`
with network access and pins reproducibility via outputHash.

Closes cheaper-inference#13075
@diegosouzapw

Copy link
Copy Markdown
Collaborator

Thanks — this is a clean, idiomatic fixed-output derivation for the workspace-lockfile
problem, and --ignore-scripts is a nice touch security-wise. Two things before merge: the
pinned version in nix/omniroute.nix is 3.8.50, which is now behind release/v3.8.51 — will
need a version bump + a recomputed outputHash. And since this sandbox doesn't have a Nix
toolchain, I wasn't able to actually run nix build .#default to confirm the hash — could you
(or whoever merges) do one real build/run before landing this, per your own test plan?

Ran the real `nix build .#default` on x86_64-linux, which the original
derivation would have failed:

- The pinned outputHash was wrong (got sha256-FV/hBAt... vs the pinned value).
- The FOD ran fixupPhase and wrapProgram, which patched shebangs to
  /nix/store bash paths. That made the hash depend on the nixpkgs bash
  version and adds store references a fixed-output derivation must not have.
- The published tarball ships no lockfile, so transitive dependencies
  floated to whatever was newest at build time and would drift the hash.
- The npm tree has platform-specific binaries (sharp, @next/swc, esbuild),
  so a single hash cannot be valid for the linux and darwin platforms that
  were advertised.

Split into two stages: a network FOD that only runs `npm install -g` with
fixup disabled and `--before=<publishedAt>` to pin resolution, and a normal
derivation that wraps the bins with the matching Node.js without copying the
multi-GB tree. Hashes are now per system; only x86_64-linux is listed.

Verified on x86_64-linux: `nix build .#default` succeeds, `omniroute
--version` and `--help` work, the server starts from the read-only store,
login and password/settings changes work and persist across a restart, and
`nix build --rebuild` reproduces the same hash.

Stays on 3.8.50: omniroute@3.8.51 is not published to npm yet.
Restore the original flake.nix description and the whitespace line in
shellHook so the flake.nix diff is only the new `packages` outputs. Replace
the unverified "350+ providers, 1200+ models" package description with
wording taken from AGENTS.md, and reduce the README note to the one
user-facing fact (x86_64-linux only), matching the neighbouring install
sections.
The npm version changes what `npm install -g` produces, so it is part of
the fixed-output hash. Build the package with nodejs_24 (npm 11), matching
the dev shell fix proposed in cheaper-inference#14613, and recompute the hash: the Node 22
hash no longer matches under npm 11.

Only the package is pinned. The shared `nodejs` binding used by the dev
shell is left untouched so this does not conflict with cheaper-inference#14613.

Verified on x86_64-linux with Node 24.16.0: `nix build .#default`
succeeds, the server starts from the store, and login plus password and
settings changes work and persist across a restart.
Replace the fixed-output `npm install -g` with `buildNpmPackage` and
`importNpmLock`. A global install ignores the manifest's `overrides`, so
the old package shipped adm-zip 0.5.18 against the ^0.6.0 pin. This
build applies all 33 overrides.

`nix/package.json` is the published manifest minus `workspaces` and
`devDependencies`. The dev tools' nested overrides pin conflicting
versions (undici, js-yaml), which makes npm ask the registry for
metadata and fail offline. `nix/package-lock.json` is generated from it.

There is no output hash to maintain: dependencies are fetched by their
lockfile integrity and the tarball hash is npm's `dist.integrity`.
`scripts/release/update-nix-package.mjs` updates all three after an npm
release and needs only npm.
@Ansh-Sonkusare

Copy link
Copy Markdown
Author

Ran the real build: nix build .#default builds and runs on x86_64-linux (server starts, login and password change work, data persists in DATA_DIR across restarts).

On the bump: omniroute@3.8.51 isn't on npm yet (latest is 3.8.50, and 3.8.51 returns 404) and there's no v3.8.51 tag, so the package stays on 3.8.50 for now.

I also moved the package off the fixed-output npm install -g to buildNpmPackage + importNpmLock with a generated lockfile. A global install ignores the manifest's overrides (the old build shipped adm-zip 0.5.18 against the ^0.6.0 pin). This one applies them, and there's no output hash anymore.

Could the Nix bump go into each npm release? After publishing:

node scripts/release/update-nix-package.mjs <version>

It needs npm only, no Nix. It regenerates nix/package.json, nix/package-lock.json and the tarball hash, and fails early if the lockfile wouldn't install offline.

@diegosouzapw diegosouzapw added the deferred-v3.8.52 Grande demais / suspeito para o lote atual; precisa de sessão dedicada no ciclo v3.8.52 label Sep 28, 2026
@diegosouzapw diegosouzapw changed the title nix: add fixed-output package derivation [defer] nix: add fixed-output package derivation Sep 28, 2026
@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.51 to release/v3.8.52 September 29, 2026 11:26
@diegosouzapw

Copy link
Copy Markdown
Collaborator

Re-homed to release/v3.8.52: v3.8.51 entered its release freeze, so the branch now belongs to the release captain and development continues on the next cycle. Nothing is wrong with this PR — it just needed a live base. No action needed from you; CI will re-run against the new base.

…in the updater

npm 12 wraps `npm view --json` in an array even for an exact version and
prints `npm pack --json` as an object keyed by package name, so the updater
failed with 'has no sha512 integrity' before touching any file. Accept both
shapes, then regenerate nix/package.json, nix/package-lock.json and the
tarball hash for the now-published 3.8.51.
@diegosouzapw diegosouzapw removed the deferred-v3.8.52 Grande demais / suspeito para o lote atual; precisa de sessão dedicada no ciclo v3.8.52 label Oct 1, 2026
@diegosouzapw diegosouzapw changed the title [defer] nix: add fixed-output package derivation nix: add fixed-output package derivation Oct 1, 2026
…ckage structure

The CLI's serve paths spawn a bare "node" and its runtime installer calls npm, neither
of which a NixOS user has on PATH. Wrap every bin from buildNpmPackage with
wrapProgram --prefix PATH so the pinned nodejs (node + npm) is always found, leaving the
lib/node_modules layout untouched.

Add a node:test structural guard for flake.nix, nix/* and the updater script: the
buildNpmPackage + importNpmLock approach, the Node 24 pin, the PATH wrapper, manifest /
lockfile / tarball-hash consistency, offline-resolvable lock entries, the
better-sqlite3 prebuilt (no install script), the adm-zip override and the shell-free
updater. nix build itself is not run by this test.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
@diegosouzapw

Copy link
Copy Markdown
Collaborator

Hi @Ansh-Sonkusare — closing this pull request to clear the open queue. The branch nix-packaging is kept, so the commits stay. Comment here if it should be reopened.

@diegosouzapw

Copy link
Copy Markdown
Collaborator

Hi @Ansh-Sonkusare — reopening this pull request. The close was a mistake, and it is back in the merge queue. The branch nix-packaging was kept.

@diegosouzapw diegosouzapw reopened this Oct 10, 2026
@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.52 to release/v3.8.53 October 19, 2026 13:37
@diegosouzapw

Copy link
Copy Markdown
Collaborator

Re-homed to release/v3.8.53: v3.8.52 entered its release freeze, so the branch now belongs to the release captain and development continues on the next cycle. Nothing is wrong with this PR — it just needed a live base. No action needed from you; CI will re-run against the new base.

@diegosouzapw

Copy link
Copy Markdown
Collaborator

Thanks @Ansh-Sonkusare, the move to buildNpmPackage + importNpmLock with a generated lockfile is the right call, and the structural tests (9/9 green on my side against the current release tip) pin the decisions that bit you earlier. Before we land it: (1) please run scripts/release/update-nix-package.mjs against the latest published version (3.8.52 on npm now, 3.8.53 soon), since nix/package.json is still pinned to 3.8.51; (2) please run nix build .#default + nix run .#default -- --help after the bump and paste the result, because we have no Nix toolchain on the maintainer side and the last wrapProgram commit has not been verified by a real build; (3) add a changelog fragment, e.g. changelog.d/maintenance/13076-nix-package.md; (4) please drop the 'Generated with Claude Code' footer from the PR description (project rule: no AI attribution in commit/PR metadata). Your commits are kept as-is, and we will merge through GitHub so you get the credit.

Regenerated with scripts/release/update-nix-package.mjs 3.8.52 (npm 12.0.2):
nix/package.json is the 3.8.52 manifest minus workspaces/devDependencies,
nix/package-lock.json is re-resolved with --before=<publish time> and passes
the offline npm ci dry run, and the tarball hash in nix/omniroute.nix is the
registry sha512 integrity of omniroute@3.8.52. Adds the changelog fragment.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hold-vps PR verde, merge aguardando validação live (release-drain)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Provide a Nix package derivation for OmniRoute

2 participants