The lnbits regtest test harness (tests/regtest/helpers.py) authenticates to
bitcoind with -rpcuser=lnbits -rpcpassword=lnbits, but bitcoind was cookie-only,
so mine_blocks / pay_onchain / create_onchain_address (and any bitcoind-using
regtest test) failed with "Incorrect rpcuser or rpcpassword".
Add -rpcauth for user lnbits (password lnbits). rpcauth does not set
rpcpassword, so the auto-generated .cookie is still produced and the LN nodes'
--bitcoind.rpccookie auth keeps working. Verified: both cookie and
lnbits/lnbits creds authenticate; wrong creds rejected. Surfaced while
validating aiolabs/lnbits#53 (native on-chain receive/send) against real lnd-1.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sets LNBITS_AUTH_HTTPS_ONLY=false on the lnbits service so the regtest
stack works when the webapp dev server hits lnbits over a LAN IP
(e.g. http://192.168.0.32:5181 → http://192.168.0.32:5001) instead of
localhost. Browsers silently discard `Secure` cookies over plain HTTP
from non-loopback origins, which kills the /auth/sign-event double-
submit CSRF flow (the GET succeeds, the cookie never lands, every POST
403s).
aiolabs/lnbits#52 made the lnbits-side gate use settings.auth_https_only
for the XSRF-TOKEN cookie (matching the existing auth_cookie_token
behavior). With that fix on dev + this env var here, the regtest stack
finally lets the bookmark/RSVP flow round-trip from a LAN-IP browser.
Production deploys leave the setting unset (default true) — Secure
stays on, behavior unchanged.
LNbits now fail-closes at boot without LNBITS_KEY_MASTER (aiolabs/lnbits#9
PR #17), and account provisioning routes through the nsec bunker
(aiolabs/lnbits#18 phase 2.1+2.2) when LNBITS_NSEC_BUNKER_* are set, so
both wiring blocks are required for the dev stack to boot and serve a
webapp signup. Also covers:
- LNBITS_CORS_ALLOWED_ORIGINS for the standalone webapp dev ports
(aiolabs/lnbits PR #31; standalone hubs 5173 + 5180-5187 across the
three browser-distinct origins localhost / 192.168.0.32 / 127.0.0.1).
- NOSTR_TRANSPORT_ROSTER_REQUIRED to reject kind-21000 RPCs from
unregistered senders rather than the silent-drop-via-auto-create
failure mode caught 2026-05-30 (aiolabs/lnbits#42, satmachineadmin#20).
- Bunker reliability: restart=unless-stopped so the watchdog's clean
exit(0) on prolonged relay-disconnect gets auto-recovered, plus
NSEC_BUNKER_DISABLE_WATCHDOG=1 to keep the bunker idling patiently
through lnbits rebuilds longer than the 60s grace window, and
NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE so RemoteBunkerSigner clients don't
need to drive a per-restart unlock_key RPC (aiolabs/nsecbunkerd#16).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two changes to the local regtest's bunker service, both tied to the
#7-diagnosis effort on aiolabs/nsecbunkerd:
1. Build context now defaults to ~/dev/nsecbunkerd/dev (the dev worktree)
instead of ~/dev/nsecbunkerd/master. The dev branch carries the
diagnosis series — wrong-kind error response fix, prisma migration
entrypoint, nix flake corrections, transport instrumentation. The
master worktree stays clean at the pre-diagnosis baseline (e39eaa6)
for reference; once dev is merged to master, this default can swap
back. NSECBUNKER_SRC override unchanged.
2. NSEC_BUNKER_DEBUG_TRANSPORT env passthrough. Set to '1' to enable
per-relay PUBLISHED / PUBLISH_FAILED + REQUEST_IN / RESPONSE_SENT
instrumentation in the bunker. Default off so day-to-day regtest
logs stay quiet.
See coordination log entries 2026-05-27T14:30Z (full #7 diagnosis) and
T16:30Z (dev branch hand-off).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires the nsec bunker daemon (Pablo's nsecBunker, forked to
aiolabs/nsecbunkerd) into the dev compose for phase 2 of
aiolabs/lnbits#9. Build context defaults to
\${NSECBUNKER_SRC:-/home/padreug/dev/nsecbunkerd/master} so the
canonical fork checkout is the source of truth — keeps all the
upstream-rot patches (Dockerfile npm→pnpm, ndk 2.8.1 pin,
pingOrDie disable, startKey nip19.decode — issues #1, #2, #3, #4,
#8 on aiolabs/nsecbunkerd) in one tracked tree instead of a local
shallow clone.
Admin npub via NSECBUNKER_ADMIN_NPUBS env (in .env). SQLite + JSON
config persisted under ./data/nsecbunker. Mirrors upstream's
upstream docker-compose memory caps.
.gitignore picks up the legacy ./nsecbunker/ local clone that the
LNBITS_SRC-style override now bypasses; left there to avoid
accidental staging if someone re-clones it for ad-hoc work.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pict-rs itself doesn't emit Access-Control-* headers; production papers
over that with an nginx vhost (deploy/server-deploy/modules/services/
pict-rs.nix), which the dev compose was claiming to mirror but didn't.
Cross-origin uploads from the webapp dev server got blocked.
Move pict-rs to internal-only (`expose`) and add a pict-rs-nginx sidecar
publishing :6033, reusing the exact CORS block from the prod nix
module. Closes the dev/prod divergence so browser upload behavior
matches between local and deployed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The webapp and several lnbits extensions hit pict-rs for image
uploads (NIP-94/96 attachments, profile pictures, market listings,
etc.). Until now there was no local pict-rs for the dev stack to
talk to, so any client code touching that path either had to point
at a remote deployed instance or be tested without exercising the
upload flow.
Mirrors the deploy flake's services.pict-rs:
- same port (6033) as modules/services/pict-rs.nix, so URLs
written for prod just work locally with a host swap;
- asonix/pictrs:0.5 (the upstream image; current stable major);
- user "0:0" + ./data/pict-rs:/mnt to match the storage pattern
other dev-stack containers use here.
Bohm's firewall already opens 6033 (see /etc/nixos/configuration.nix),
so LAN devices (phones for image-upload UX testing) can reach it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two small fixes that surfaced during the v2-bitspire end-to-end test
on 2026-05-15 against a real Sintra ATM:
1. `NOSTR_TRANSPORT_PRIVATE_KEY` / `NOSTR_TRANSPORT_PUBLIC_KEY` are
now forwarded from the local `.env` into the lnbits container's
environment. Without a pinned key LNbits auto-generates a fresh
server keypair on every container restart, which breaks any ATM
previously provisioned against the old pubkey (encryption target
no longer exists from LNbits' point of view → RPCs land on the
relay but the dispatcher never picks them up → cash-out hangs at
"generating invoice"). The `.env` file is gitignored so the actual
keypair stays out of the repo; rotate by regenerating + re-
provisioning all ATMs.
2. `AUTH_HTTPS_ONLY: "false"` — LNbits' auth cookies default to
requiring HTTPS, which blocks LAN access from a non-localhost
browser (e.g. another machine on 192.168.0.x reaching the dev
instance). Safe to disable for the dev stack; production-shaped
deployments must keep it true.
Sharding only fires when an outbound RPC response exceeds the per-
event content cap. With the production default (40_000) it takes
hundreds of seeded payments to make `list_payments` trip sharding —
the test_transport_suite.py test #2 was reproducibly hitting ~39K
just shy of the threshold even with 90 round-trips and 600-char
memos.
Lowered to 20_000 in the dev compose so the same test trips
sharding with ~60 fat-memo payments (~20s of seed time). Production
deployments leave this unset and inherit the 40_000 default.
The lower threshold doesn't mask any real behavior — the shard
envelope is identical at either threshold, and the unit tests in
LNbits exercise the boundary cases independently
(tests/unit/test_nostr_transport.py::test_split_content*).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The nostr transport's --flow subscribe driver flow creates two fresh
accounts via the transport's auto-account-creation path and needs the
payer one to have funds. LNBITS_DEMO_MODE auto-credits 1M sats to the
default wallet on account creation (gated to FakeWallet + this opt-in,
see lnbits/core/services/users.py:_demo_mode_enabled).
The previous round's nostr-transport env wiring already lives in this
file; this adds the demo flag so the new --flow subscribe demo runs
out of the box.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds NOSTR_TRANSPORT_ENABLED + NOSTR_TRANSPORT_RELAYS so the
nostr-native-transport branch can be exercised end-to-end out of the
dev container without manual env overrides each spin-up.
Points the transport at the in-container nostrrelay extension (relay
id "test", which must be created once via the LNbits admin UI). The
transport's reconnect loop tolerates the relay not being ready at
startup — it retries every 5s — so first-time setup is just: bring
up the stack, create the relay in the UI, watch the transport log
"connected to ws://localhost:5001/nostrrelay/test".
Pairs with branch nostr-native-transport on aiolabs/lnbits.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Find bash via PATH rather than hard-coding /bin/bash, for systems
(NixOS, macOS w/ homebrew bash) where the system bash isn't current.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The castle LNbits extension was renamed to libra. Updates the
default-install / default-user env vars in docker-compose.dev.yml
and the fava-url pin in lnbits-entrypoint.sh (DB filename, slug,
log prefix, comments). The entrypoint script was previously
untracked — tracking it now so the rename persists for fresh
checkouts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Default to ~/dev/lnbits/demo, override with env var:
LNBITS_SRC=~/dev/lnbits/dev docker compose -f docker-compose.dev.yml up -d --build
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Runs just LNbits + Fava — no LND nodes, Bitcoin Core, or Boltz.
For testing extension changes without full regtest overhead.
Usage: docker compose -f docker-compose.dev.yml up -d
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds litd v0.16.0-alpha in remote mode connecting to lnd-1.
This enables Loop Out functionality for submarine swaps.
- Exposes ports 8443 (HTTPS) and 8080 (HTTP)
- UI password: testpassword123
- Configured for regtest network
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This allows easier seeding and management of lnbits data:
- data/lnbits/ for runtime data
- data/lnbits-seed/ for pre-populated seed data
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>