- nix devShell uses nixos-25.05's prisma-engines 6.7.0 (has libquery_engine.node) — the 7.x problem is the system/unstable channel only, not the flake's devShell (corrects an earlier overstatement; #30 closed as invalid). - start.js migrate-on-boot is a no-op on nix but IS the migration path on docker (image ENTRYPOINT) — don't assume it's dead everywhere (#31). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.5 KiB
nsecbunkerd migration & DB-maintenance runbook
Operational notes for applying schema migrations and ACL/pairing maintenance on deployed, LNbits-connected nsecbunkerd instances.
⚠️ Never full-wipe nsecbunker.db on an LNbits-connected instance
The nsecbunkerd ↔ LNbits pairing is split across both systems:
- Bunker (
nsecbunker.db): per-accountKeyUserbinding (keyed by LNbits's stable client pubkey) + redeemedToken+ a sharedPolicy. - LNbits (
accounts.signer_config,RemoteBunkerSigner):{token, client_nsec, policy_id}.
RemoteBunkerSigner.sign_event() signs directly with the stored client_nsec
— it does NOT re-connect/re-redeem, and there is no auto-repair on restart or
sign-failure. provision() runs only at new-account creation and mints a NEW
npub (which changes the user's nostr identity).
Consequence of a full nsecbunker.db wipe: the KeyUser bindings are
deleted → every LNbits account's stored config dangles → all signing fails, and
the only standard "repair" (provision()) changes identities. Do not do it.
Correct way to strip the #24 materialized photocopies
Post-#27, token grants are evaluated live via the ACL step-4 Token → Policy → PolicyRule join, so the old materialized SigningCondition rows are redundant
— and, written with expiresAt = NULL, they would keep granting past a token's
expiry (silently re-opening #24 for already-paired clients). Strip them with a
targeted delete that preserves the pairing:
-- Verify first.
SELECT COUNT(*) FROM Token WHERE redeemedAt IS NOT NULL; -- bindings to preserve
SELECT COUNT(*) FROM SigningCondition; -- photocopies to strip
-- Keeps KeyUser + Token + Policy intact. Live-token clients keep working
-- untouched; only the stale photocopies are removed.
DELETE FROM SigningCondition;
Run against each instance's nsecbunker.db. If an instance was already
full-wiped, recover by restoring the pre-wipe nsecbunker.db backup, then run
the targeted delete.
Manual-override grants (
add_signing_condition, web-approval) also live inSigningCondition. On an LNbits-only bunker there typically are none, so a blanketDELETE FROM SigningConditionis safe. If an instance uses manual overrides, delete only the policy-derived rows you intend to strip.
Keys are never in the DB
Key material lives in nsecbunker.json (keys), never in nsecbunker.db. A DB
wipe loses ACL/pairing state, never keys. LNbits holds the bunker admin nsec
(LNBITS_NSEC_BUNKER_ADMIN_NSEC) and is the sole admin client.
Schema migrations
On the nix deploy, migrations are applied by the deploy's prisma migrate deploy, not by the daemon — start.js's npm run prisma:migrate step fails in
the read-only nix store (no npm on PATH) and is a redundant no-op there (#31).
On docker, by contrast, start.js IS the migration path (it's the image
ENTRYPOINT), so the step is not dead everywhere. After adding a migration, make
sure the path that applies for your target actually runs it.
Prisma on NixOS: the flake pins nixos-25.05, whose prisma-engines is
6.7.0 (ships libquery_engine.node) — both the devShell and the deploy's
package.nix use it, so prisma (and the npm run test:integration suite) work
in nix develop out of the box. Heads-up: on nixos-unstable / a system
<nixpkgs> channel, the bare prisma-engines attr is 7.x with no
libquery_engine.node; don't run the repo's prisma against an unstable channel.