fix(nix): include prisma CLI + scripts/, wrapper invokes start.js
Some checks failed
Docker image / build-and-push-image (push) Has been cancelled

Three correctness fixes to the nix derivation that mirror the Dockerfile
correctness fixes:

1. Drop `pnpm prune --prod --ignore-scripts` from the build phase. The
   prune step removed the prisma CLI (devDependency) from the output,
   so the runtime invocation of `prisma migrate deploy` had nothing to
   exec. Same trap the upstream Dockerfile fell into via `--prod` install.

2. Copy `scripts/` into `$out/share/nsecbunkerd/` alongside dist,
   node_modules, prisma, templates. Without it the launcher script
   (which contains the migration step) wasn't present.

3. The makeWrapper target switches from `dist/index.js` to
   `scripts/start.js`. Same change the Dockerfile ENTRYPOINT got in
   the previous commit. Also adds nodejs_20 to PATH so `npm` is
   resolvable from inside start.js, and drops `--chdir` so the caller
   (systemd, docker compose) controls cwd — start.js now resolves
   sibling paths from `__dirname`, independently committed.

The `patchNdk` substitution narrows from the old `workspace:*` form
(no longer in the package.json after fork commit 06272c8) to the
current `"2.8.1"` → `"^2.8.1"` rewrite needed to align package.json
with the lockfile under --frozen-lockfile.

Remaining known gap: nixpkgs ships prisma-engines 7.7.0 while the
JS prisma CLI in node_modules is 5.4.1, an RPC vocabulary mismatch
that breaks the migrate step at runtime (`Method not found:
listMigrationDirectories`). Either bump prisma JS to ^7.x or overlay
prisma-engines to 5.4.1. Out of scope for this commit; docker build
unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-05-27 17:08:42 +02:00
commit 662dd21a60

View file

@ -13,12 +13,17 @@
}: }:
let let
# package.json pins `@nostr-dev-kit/ndk: "workspace:*"` but the lockfile # Fork commit `06272c8` ("pin @nostr-dev-kit/ndk to 2.8.1 instead of
# resolves `^2.8.1`. With --frozen-lockfile pnpm refuses the mismatch, # workspace:*") changed package.json to a pinned `"2.8.1"`, but the
# so rewrite the spec to match the lockfile. # pnpm-lock.yaml still expresses the spec as `"^2.8.1"` (the way
# `pnpm add` originally generated it). pnpm with --frozen-lockfile
# rejects that mismatch. Patching package.json to use the caret form
# is non-semantic (2.8.1 is still the resolved version) and aligns
# both files. Same fix the Dockerfile-side already handles via
# `--no-frozen-lockfile`; in nix we prefer frozen + a targeted patch.
patchNdk = '' patchNdk = ''
substituteInPlace package.json \ substituteInPlace package.json \
--replace-fail '"@nostr-dev-kit/ndk": "workspace:*"' \ --replace-fail '"@nostr-dev-kit/ndk": "2.8.1"' \
'"@nostr-dev-kit/ndk": "^2.8.1"' '"@nostr-dev-kit/ndk": "^2.8.1"'
''; '';
@ -77,7 +82,12 @@ stdenv.mkDerivation (finalAttrs: {
pnpm prisma generate pnpm prisma generate
pnpm build pnpm build
pnpm prune --prod --ignore-scripts # Do NOT `pnpm prune --prod` here — the prisma CLI lives in
# devDependencies and `scripts/start.js` invokes it at boot via
# `npx prisma migrate deploy`. Without the CLI, the migration step
# silently fails (npx falls back to downloading prisma fresh, which
# OOMs on most containers) and the SQLite db stays empty. See
# `aiolabs/nsecbunkerd#7` diagnosis 2026-05-27.
find node_modules -xtype l -delete find node_modules -xtype l -delete
runHook postBuild runHook postBuild
@ -87,14 +97,24 @@ stdenv.mkDerivation (finalAttrs: {
runHook preInstall runHook preInstall
mkdir -p $out/{bin,share/nsecbunkerd} mkdir -p $out/{bin,share/nsecbunkerd}
cp -r dist node_modules prisma templates package.json \ # scripts/ MUST be copied — it contains the start.js launcher that
# runs `prisma migrate deploy` before spawning the daemon. The
# upstream packaging (and the upstream Dockerfile) bypassed this by
# invoking dist/index.js directly, leaving migrations unapplied.
cp -r dist node_modules prisma scripts templates package.json \
$out/share/nsecbunkerd/ $out/share/nsecbunkerd/
# Wrapper invokes scripts/start.js, which runs `prisma migrate deploy`
# then spawns dist/index.js. start.js resolves sibling paths from
# __dirname, so the caller (systemd unit, docker compose, etc.) can
# set its own WorkingDirectory for the writable state dir without
# interfering with how the launcher finds its own package files.
# NSEC_BUNKER_CONFIG_DIR can override the config directory location;
# by default it's `./config` relative to cwd.
makeWrapper ${lib.getExe nodejs_20} $out/bin/nsecbunkerd \ makeWrapper ${lib.getExe nodejs_20} $out/bin/nsecbunkerd \
--chdir $out/share/nsecbunkerd \ --add-flags $out/share/nsecbunkerd/scripts/start.js \
--add-flags $out/share/nsecbunkerd/dist/index.js \
--set NODE_ENV production \ --set NODE_ENV production \
--prefix PATH : ${lib.makeBinPath [ openssl ]} \ --prefix PATH : ${lib.makeBinPath [ openssl nodejs_20 ]} \
${ ${
lib.concatStringsSep " \\\n " ( lib.concatStringsSep " \\\n " (
lib.mapAttrsToList (n: v: "--set ${n} ${lib.escapeShellArg v}") prismaEnv lib.mapAttrsToList (n: v: "--set ${n} ${lib.escapeShellArg v}") prismaEnv