Files
nixpkgs/overlays/mods/n8n.nix
T
m3ta-chiron c22cb5f3a7 n8n: 2.36.8 -> 2.37.9, migrate to pnpm 11, harden update.sh
n8n >= 2.37.0 demands pnpm >= 11.22.0 via engines.pnpm and serialises
patchedDependencies as plain scalars in pnpm-lock.yaml (same
lockfileVersion '9.0'), which pnpm 10 cannot install. The pinned nixpkgs
only ships pnpm_11 11.17.0, so:

- build with pnpm_11 + fetcherVersion 4 and relax the engines.pnpm gate
  in package.json (relaxPnpmEngine) for both fetchPnpmDeps and the main
  build; swap pnpm_10 -> pnpm_11 in nativeBuildInputs
- drop the workaround once nixpkgs ships pnpm >= 11.22

update.sh: detect ERR_PNPM_UNSUPPORTED_ENGINE /
ERR_PNPM_LOCKFILE_CONFIG_MISMATCH with actionable hints, sync
tests/n8n-overlay-test.nix expectations (checks were stale at 2.32.6),
guard against leftover fake-hash sentinels, and run from the repo root
so the relative nix --expr paths resolve.

Verified: n8n-overlay check green, full n8n 2.37.9 build green.
2026-09-04 08:04:34 +02:00

75 lines
3.1 KiB
Nix

{prev}: let
# n8n >= 2.32 replaced the sheetjs-CDN `xlsx@0.20.2` tarball (which lacked an
# integrity checksum and had to be patched into pnpm-lock.yaml) with the
# regular npm package `@e965/xlsx@0.20.3`, which already carries an integrity
# field. The old lockfile-integrity workaround is therefore obsolete and has
# been removed.
#
# n8n >= 2.37.0 demands pnpm >= 11.22.0 via `engines.pnpm`, but the pinned
# nixpkgs only ships pnpm_10 (10.34.5) and pnpm_11 (11.17.0) — both too old.
# pnpm enforces that gate for ITSELF regardless of `engine-strict`, so both
# fetchPnpmDeps and the main build die with ERR_PNPM_UNSUPPORTED_ENGINE
# before any hash mismatch is even reached. Additionally n8n's lockfile,
# while still declaring lockfileVersion '9.0', now serialises
# patchedDependencies as plain `name@version: hash` scalars (no `path:`
# mapping), which pnpm 10 cannot parse (ERR_PNPM_LOCKFILE_CONFIG_MISMATCH).
# We therefore build with pnpm_11 + fetcherVersion 4 and relax the engine
# gate in package.json. Drop the sed once nixpkgs ships pnpm >= 11.22 and
# this overlay's nixpkgs pin has caught up.
relaxPnpmEngine = ''
sed -i -E 's/"pnpm": *"[^"]*"/"pnpm": "*"/' package.json
'';
in
prev.n8n.overrideAttrs (finalAttrs: previousAttrs: {
version = "2.37.9";
src = prev.fetchFromGitHub {
owner = "n8n-io";
repo = "n8n";
tag = "n8n@${finalAttrs.version}";
hash = "sha256-DFoXCtn+rM69ISKVV2aet8LfGCOsN29yuyYOpz0f71U=";
};
pnpmDeps = prev.fetchPnpmDeps {
inherit (finalAttrs) pname version src;
pnpm = prev.pnpm_11;
fetcherVersion = 4;
postPatch = relaxPnpmEngine;
hash = "sha256-4SFl0JD4iQc4tQFtJvNWkYCVyT6sj7+id/BrJEaTl8E=";
};
postPatch = (previousAttrs.postPatch or "") + relaxPnpmEngine;
# Swap pnpm_10 -> pnpm_11 from the inherited nativeBuildInputs: upstream
# n8n calls pnpm directly during the build (install/build/prune) and pnpm 10
# cannot parse the pnpm-11 lockfile. The top-level pnpmConfigHook stays as
# is — it discovers the fetcher version from pnpmDeps' .fetcher-version.
nativeBuildInputs = builtins.map (x:
if (x.outPath or null) == prev.pnpm_10.outPath
then prev.pnpm_11
else x)
previousAttrs.nativeBuildInputs;
preBuild =
(previousAttrs.preBuild or "")
+ ''
if [ ! -e node_modules/sass-embedded ] && [ -e node_modules/.pnpm/node_modules/sass-embedded ]; then
ln -s .pnpm/node_modules/sass-embedded node_modules/sass-embedded
fi
if [ ! -e node_modules/sqlite3 ] && [ -e node_modules/.pnpm/node_modules/sqlite3 ]; then
ln -s .pnpm/node_modules/sqlite3 node_modules/sqlite3
fi
'';
# Self-contained update script (./update.sh) — fetches latest stable
# release from n8n-io/n8n, recomputes both src and pnpmDeps hashes.
# The CI workflow in .gitea/workflows/nix-update.yml discovers and runs it.
passthru = (previousAttrs.passthru or {}) // {updateScript = ./update.sh;};
meta =
previousAttrs.meta
// {
changelog = "https://github.com/n8n-io/n8n/releases/tag/n8n@${finalAttrs.version}";
};
})