Add BrollyZapper - #6049
Open
davotoula wants to merge 2 commits into
Open
Add BrollyZapper#6049davotoula wants to merge 2 commits into
davotoula wants to merge 2 commits into
Conversation
davotoula
added a commit
to davotoula/brollyzapper
that referenced
this pull request
Sep 3, 2026
… against upstream HEAD getumbrel/umbrel-apps#6049 is open; the manifest's submission field is the one thing the linter could not accept before the PR existed. The README's last-verified line moves to today's upstream HEAD (318cdcf, 391 apps): IP, neighbours and port all still free.
Author
Author
|
@nmfretz and the team, is there any other information needed for adding apps to umbrel? Or maybe you are all busy with umbrel 2.0 preparations? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.






Type
New app
App
brollyzapper0.1.18Summary
BrollyZapper adds Nostr zap receiving (NIP-57) and Nostr Wallet Connect (NIP-47)
to an LND node the user already runs. It depends on
lightningand adds no nodeof its own.
The store's dedicated NWC app,
alby-nostr-wallet-connect, is deprecated by itsdevelopers and carries
disabled: true. This fills that gap, and does so with amaterially tighter credential posture than any existing app that talks to LND —
see Notes.
Verification
Umbrel testing performed (2026-09-02, 0.1.17): fresh install — uninstall, then install
through the Umbrel dashboard with
lightningalready running (30 s to Open, both images pulledfrom GHCR, digests matching the manifest); setup through
app_proxy; the proxy whitelist probedfrom a session-less client (
/healthand the LNURL paths answer anonymously, every other pathredirects to Umbrel's login) and the address fetched from the public internet through a tunnel;
real workflow — one zap received from Amethyst with its kind-9735 receipt read back off a
public relay, and one plain LNURL payment from Primal; restart through the dashboard
(
apps.restart.mutate, 28 s, containers recreated) with settings, wallet history and the receivecredential surviving unchanged; ten idle minutes of settled logs with nothing above INFO. The
receive-only posture was verified by inspection:
recv.macaroonpresent, nospend.macaroon.In-place update (2026-09-03, 0.1.17 → 0.1.18 through the dashboard's Update button, 30 s):
digests on the box match the manifest, no migration, both credentials survived the container
recreate byte-identical with no re-bake, the guard re-registered its spend-cap middleware, the
24-hour spend window carried across, one zap and one plain payment received and one NWC payment
sent afterwards, a further restart with everything intact, ten idle minutes with nothing above
INFO.
Environment tested:
1.7.4, Raspberry Pi 4Architecture tested:
6.18.34+rpt-rpi-v8aarch64Known lint warnings or caveats: none.
npm run lint:apps -- brollyzapper --check-imagesis clean, 0 warnings. Both images are pinned by multi-arch indexdigest and carry
linux/amd64+linux/arm64.Notes
Dependency.
lightning. The transitivebitcoinexport suppliesAPP_BITCOIN_NETWORK, used to locate the macaroon.LND credential access — the part worth reviewing. The package mounts two
individual files from the lightning app's data dir, read-only:
Twenty apps in the store mount
admin.macaroon. Of those,btcpay-server,bluewallet,bolt12-pay,fedimint-gatewayandalby-nostr-wallet-connectmount
${APP_LIGHTNING_NODE_DATA_DIR}:/lnd:ro— the whole directory, includingwallet.dbandchannel.backup. With Umbrel's default wallet password,wallet.dbis the seed.albyhubmounts the same directory by hardcoded pathwhile declaring
dependencies: [].This package is the only one in the store that mounts
admin.macaroonat filegranularity, and it never puts it in the container with the attack surface:
guardholdsadmin.macaroonand has no listener of any kind. Its onlyinput is a unix socket in a shared volume, with a fixed four-operation API.
serverholds all of it — HTTP, nostr relays, sqlite — and never seesadmin.macaroon. It consumes a receive-only macaroon the guard bakes: five RPCmethods, none able to move a satoshi.
A repository lint asserts the split rather than trusting review, and it is
verified by planting the violation.
No host access. No Docker socket, no
privileged, no device mounts, no extracapabilities, no
network_mode: host, no raw published ports.Umbrel auth stays on.
PROXY_AUTH_WHITELISTis narrowed to the three routesanonymous LNURL clients on the public internet must reach and cannot send an
Umbrel cookie to:
/health,/.well-known/lnurlp/*,/lnurlp/*. Everything elsesits behind Umbrel auth and the app's own login. A lint asserts the whitelist
equals the app's public route set exactly, because a public route Umbrel still
gates breaks anonymous clients with no visible error.
Credentials.
deterministicPassword: true, and the package genuinely wiresADMIN_PASSWORDto${APP_PASSWORD}, so what Umbrel displays is what logs in.Login is password-only, hence
defaultUsername: "". The session secret is apurpose-labelled
derive_entropyinexports.sh, notAPP_SEEDreused and not aconstant.
backupIgnore: [data/credentials]. That volume holds the receive macaroon,which in a stolen backup would stream every invoice on the node over LND's
Tor-published gRPC. Nothing is lost by excluding it: the guard re-bakes on start,
so a restore comes back with a fresh, correctly caveated credential rather than a
stale one. The database stays in backup — it holds the zap-receipt signing key,
and losing it changes the nostr pubkey the lightning address advertises.
Static IP.
10.21.21.14, needed because the spend macaroon carries anipaddrcaveat that must match the server container exactly. Verified freeagainst the whole store on
2026-09-03(getumbrel/umbrel-apps@318cdcf, 391 apps);3033likewise free across all manifestsand raw port mappings.
Icon
Logo reference: https://github.com/davotoula/brollyzapper/blob/main/assets/icon.svg
(an upturned umbrella catching zaps, in nostr purple, with
BZon the canopy; letterformsare path data, so it renders without the font). A 256×256 PNG raster is attached in the
first comment below.
Screenshots
Five screenshots of the running UI at 1440×900 (Wallet, Connections, Sending, Security,
Settings) are attached in the first comment below. They are rendered from fixture data on
purpose — deterministic, and no operator's own npubs or amounts in a public listing. Nothing
artwork-shaped is committed here and
gallery: []stays empty for Umbrel to create the finalassets.
🤖 Generated with Claude Code