diff --git a/.dockerignore b/.dockerignore
index b1d8460d..4cdac613 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -23,10 +23,3 @@ mypy.ini
package-lock.json
package.json
pytest.ini
-
-.mypy_cache
-.github
-.pytest_cache
-.vscode
-bin
-dist
diff --git a/.env.example b/.env.example
index a3da8ecd..0f5e3f6e 100644
--- a/.env.example
+++ b/.env.example
@@ -18,6 +18,7 @@ ENABLE_LOG_TO_FILE=true
# https://loguru.readthedocs.io/en/stable/api/logger.html#file
LOG_ROTATION="100 MB"
LOG_RETENTION="3 months"
+
# for database cleanup commands
# CLEANUP_WALLETS_DAYS=90
@@ -186,6 +187,7 @@ BOLTZ_CLIENT_ENDPOINT=127.0.0.1:9002
BOLTZ_CLIENT_MACAROON="/home/bob/.boltz/macaroons/admin.macaroon"
# HEXSTRING instead of path also possible
BOLTZ_CLIENT_CERT="/home/bob/.boltz/tls.cert"
+BOLTZ_CLIENT_WALLET="lnbits"
# StrikeWallet
STRIKE_API_ENDPOINT=https://api.strike.me/v1
@@ -331,3 +333,4 @@ LNBITS_RESERVE_FEE_PERCENT=1.0
######################################
###### Logging and Development #######
######################################
+
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1afd181f..e92670c3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -75,14 +75,7 @@ jobs:
strategy:
matrix:
python-version: ["3.10"]
- backend-wallet-class:
- - BoltzWallet
- - LndRestWallet
- - LndWallet
- - CoreLightningWallet
- - CoreLightningRestWallet
- - LNbitsWallet
- - EclairWallet
+ backend-wallet-class: ["LndRestWallet", "LndWallet", "CoreLightningWallet", "CoreLightningRestWallet", "LNbitsWallet", "EclairWallet"]
with:
custom-pytest: "uv run pytest tests/regtest"
python-version: ${{ matrix.python-version }}
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index e35c1536..69875181 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -62,4 +62,3 @@ jobs:
platforms: linux/amd64,linux/arm64
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
- build-args: LNBITS_TAG=${{ inputs.tag }}
diff --git a/.github/workflows/appimage.yml b/.github/workflows/packaging.yml
similarity index 84%
rename from .github/workflows/appimage.yml
rename to .github/workflows/packaging.yml
index 9662b106..0426ffa3 100644
--- a/.github/workflows/appimage.yml
+++ b/.github/workflows/packaging.yml
@@ -1,27 +1,8 @@
name: Build LNbits AppImage
on:
- workflow_call:
- inputs:
- tag_name:
- description: 'The tag name for the release'
- required: true
- type: string
- upload_url:
- description: 'The upload URL for the release'
- required: true
- type: string
-
- workflow_dispatch:
- inputs:
- tag_name:
- description: 'The tag name for the release'
- required: true
- type: string
- upload_url:
- description: 'The upload URL for the release'
- required: true
- type: string
+ release:
+ types: [published]
jobs:
build-linux-package:
@@ -94,7 +75,7 @@ jobs:
# Build AppImage
wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
chmod +x appimagetool-x86_64.AppImage
- TAG_NAME=${{ inputs.tag_name }}
+ TAG_NAME=${{ github.event.release.tag_name }}
APPIMAGE_NAME="LNbits-${TAG_NAME}.AppImage"
./appimagetool-x86_64.AppImage \
--updateinformation "gh-releases-zsync|lnbits|lnbits|latest|*.AppImage.zsync" \
@@ -112,7 +93,7 @@ jobs:
- name: Upload Linux Release Asset
uses: actions/upload-release-asset@v1
with:
- upload_url: ${{ inputs.upload_url }}
+ upload_url: ${{ github.event.release.upload_url }}
asset_path: ${{ env.APPIMAGE_NAME }}
asset_name: ${{ env.APPIMAGE_NAME }}
asset_content_type: application/octet-stream
diff --git a/.github/workflows/regtest.yml b/.github/workflows/regtest.yml
index 27b9a20e..723968f1 100644
--- a/.github/workflows/regtest.yml
+++ b/.github/workflows/regtest.yml
@@ -40,8 +40,8 @@ jobs:
run: |
git clone https://github.com/lnbits/legend-regtest-enviroment.git docker
cd docker
- chmod +x ./start-regtest
- ./start-regtest
+ chmod +x ./tests
+ ./tests
sudo chmod -R a+rwx .
- name: Run pytest
@@ -63,8 +63,6 @@ jobs:
LNBITS_ENDPOINT: http://localhost:5001
LNBITS_KEY: "d08a3313322a4514af75d488bcc27eee"
ECLAIR_URL: http://127.0.0.1:8082
- BOLTZ_CLIENT_ENDPOINT: 127.0.0.1:9002
- BOLTZ_MNEMONIC: abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
LNBITS_MAX_OUTGOING_PAYMENT_AMOUNT_SATS: 1000000000
LNBITS_MAX_INCOMING_PAYMENT_AMOUNT_SATS: 1000000000
ECLAIR_PASS: lnbits
diff --git a/.github/workflows/release-rc.yml b/.github/workflows/release-rc.yml
index 50b0cc91..1a034395 100644
--- a/.github/workflows/release-rc.yml
+++ b/.github/workflows/release-rc.yml
@@ -10,29 +10,7 @@ permissions:
jobs:
- release:
- runs-on: ubuntu-24.04
- outputs:
- upload_url: ${{ steps.get_upload_url.outputs.upload_url }}
- steps:
- - uses: actions/checkout@v4
- - name: Create github pre-release
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- tag: ${{ github.ref_name }}
- run: |
- gh release create "$tag" --prerelease --generate-notes --draft
- - id: get_upload_url
- name: Get upload url of Github release
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- tag: ${{ github.ref_name }}
- run: |
- upload_url=$(gh release view "$tag" --json uploadUrl -q ".uploadUrl")
- echo "upload_url=$upload_url" >> "$GITHUB_OUTPUT"
-
docker:
- if: github.repository == 'lnbits/lnbits'
uses: ./.github/workflows/docker.yml
with:
tag: ${{ github.ref_name }}
@@ -41,7 +19,6 @@ jobs:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
pypi:
- if: github.repository == 'lnbits/lnbits'
runs-on: ubuntu-24.04
steps:
- name: Install dependencies for building secp256k1
@@ -53,10 +30,3 @@ jobs:
uses: JRubics/poetry-publish@v1.15
with:
pypi_token: ${{ secrets.PYPI_API_KEY }}
-
- appimage:
- needs: [ release ]
- uses: ./.github/workflows/appimage.yml
- with:
- tag_name: ${{ github.ref_name }}
- upload_url: ${{ needs.release.outputs.upload_url }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 212abfca..5cbe939d 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -13,8 +13,6 @@ jobs:
release:
runs-on: ubuntu-24.04
- outputs:
- upload_url: ${{ steps.get_upload_url.outputs.upload_url }}
steps:
- uses: actions/checkout@v4
- name: Create github release
@@ -23,17 +21,8 @@ jobs:
tag: ${{ github.ref_name }}
run: |
gh release create "$tag" --generate-notes --draft
- - id: get_upload_url
- name: Get upload url of Github release
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- tag: ${{ github.ref_name }}
- run: |
- upload_url=$(gh release view "$tag" --json uploadUrl -q ".uploadUrl")
- echo "upload_url=$upload_url" >> "$GITHUB_OUTPUT"
docker:
- if: github.repository == 'lnbits/lnbits'
needs: [ release ]
uses: ./.github/workflows/docker.yml
with:
@@ -43,7 +32,6 @@ jobs:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
docker-latest:
- if: github.repository == 'lnbits/lnbits'
needs: [ release ]
uses: ./.github/workflows/docker.yml
with:
@@ -53,7 +41,6 @@ jobs:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
pypi:
- if: github.repository == 'lnbits/lnbits'
runs-on: ubuntu-24.04
steps:
- name: Install dependencies for building secp256k1
@@ -65,10 +52,3 @@ jobs:
uses: JRubics/poetry-publish@v1.15
with:
pypi_token: ${{ secrets.PYPI_API_KEY }}
-
- appimage:
- needs: [ release ]
- uses: ./.github/workflows/appimage.yml
- with:
- tag_name: ${{ github.ref_name }}
- upload_url: ${{ needs.release.outputs.upload_url }}
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 621ed1da..1f53bf89 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -23,7 +23,7 @@ repos:
- id: ruff
args: [ --fix, --exit-non-zero-on-fix ]
- repo: https://github.com/rbubley/mirrors-prettier
- rev: v3.7.4
+ rev: v3.6.2
hooks:
- id: prettier
types_or: [css, javascript, html, json]
diff --git a/CUSTOM_FRONTEND_URL_SIMPLE.md b/CUSTOM_FRONTEND_URL_SIMPLE.md
deleted file mode 100644
index 96c2d052..00000000
--- a/CUSTOM_FRONTEND_URL_SIMPLE.md
+++ /dev/null
@@ -1,213 +0,0 @@
-# Custom Frontend URL - Simple Redirect Approach
-
-## Overview
-
-This is the **simplest** approach to integrate LNbits with a custom frontend. LNbits handles all authentication (login, register, password reset) and then redirects users to your custom frontend URL instead of `/wallet`.
-
-## How It Works
-
-### Password Reset Flow
-
-1. **Admin generates reset link** → User receives: `https://lnbits.com/?reset_key=...`
-2. **User clicks link** → LNbits shows password reset form
-3. **User submits new password** → LNbits sets auth cookies
-4. **LNbits redirects** → `https://myapp.com/` (your custom frontend)
-5. **Web-app loads** → `checkAuth()` sees valid LNbits cookies → ✅ User is logged in!
-
-### Login Flow
-
-1. **User visits** → `https://lnbits.com/`
-2. **User logs in** → LNbits validates credentials and sets cookies
-3. **LNbits redirects** → `https://myapp.com/`
-4. **Web-app loads** → ✅ User is logged in!
-
-### Register Flow
-
-1. **User visits** → `https://lnbits.com/`
-2. **User registers** → LNbits creates account and sets cookies
-3. **LNbits redirects** → `https://myapp.com/`
-4. **Web-app loads** → ✅ User is logged in!
-
-## Configuration
-
-### Environment Variable
-
-```bash
-# In .env or environment
-export LNBITS_CUSTOM_FRONTEND_URL=https://myapp.com
-```
-
-Or configure through LNbits admin UI: **Settings → Operations → Custom Frontend URL**
-
-### Default Behavior
-
-- **If not set**: Redirects to `/wallet` (default LNbits behavior)
-- **If set**: Redirects to your custom frontend URL
-
-## Implementation
-
-### Changes Made
-
-1. **Added setting** (`lnbits/settings.py:282-285`):
- ```python
- class OpsSettings(LNbitsSettings):
- lnbits_custom_frontend_url: str | None = Field(
- default=None,
- description="Custom frontend URL for post-auth redirects"
- )
- ```
-
-2. **Exposed to frontend** (`lnbits/helpers.py:88`):
- ```python
- window_settings = {
- # ...
- "LNBITS_CUSTOM_FRONTEND_URL": settings.lnbits_custom_frontend_url,
- # ...
- }
- ```
-
-3. **Updated redirects** (`lnbits/static/js/index.js`):
- - `login()` - line 78
- - `register()` - line 56
- - `reset()` - line 68
- - `loginUsr()` - line 88
-
- All now use:
- ```javascript
- window.location.href = this.LNBITS_CUSTOM_FRONTEND_URL || '/wallet'
- ```
-
-## Advantages
-
-### ✅ Zero Changes to Web-App
-Your custom frontend doesn't need to:
-- Parse `?reset_key=` from URLs
-- Build password reset UI
-- Handle password reset API calls
-- Manage error states
-- Implement validation
-
-### ✅ Auth Cookies Work Automatically
-LNbits sets httponly cookies that your web-app automatically sees:
-- `cookie_access_token`
-- `is_lnbits_user_authorized`
-
-Your existing `auth.checkAuth()` will detect these and log the user in.
-
-### ✅ Simple & Elegant
-Only 3 files changed in LNbits, zero changes in web-app.
-
-### ✅ Backwards Compatible
-Existing LNbits installations continue to work. Setting is optional.
-
-## Disadvantages
-
-### ⚠️ Brief Branding Inconsistency
-Users see LNbits UI briefly during:
-- Login form
-- Registration form
-- Password reset form
-
-Then get redirected to your branded web-app.
-
-**This is usually acceptable** for most use cases, especially for password reset which is infrequent.
-
-## Testing
-
-1. **Set the environment variable**:
- ```bash
- export LNBITS_CUSTOM_FRONTEND_URL=http://localhost:5173
- ```
-
-2. **Restart LNbits**:
- ```bash
- poetry run lnbits
- ```
-
-3. **Test Login**:
- - Visit `http://localhost:5000/`
- - Log in with credentials
- - Verify redirect to `http://localhost:5173`
- - Verify web-app shows you as logged in
-
-4. **Test Password Reset**:
- - Admin generates reset link in users panel
- - User clicks link with `?reset_key=...`
- - User enters new password
- - Verify redirect to custom frontend
- - Verify web-app shows you as logged in
-
-## Security
-
-### ✅ Secure
-- Auth cookies are httponly (can't be accessed by JavaScript)
-- LNbits handles all auth logic
-- No sensitive data in URLs except one-time reset keys
-- Reset keys expire based on `auth_token_expire_minutes`
-
-### 🔒 HTTPS Required
-Always use HTTPS for custom frontend URLs in production:
-```bash
-export LNBITS_CUSTOM_FRONTEND_URL=https://myapp.com
-```
-
-## Migration
-
-**No database migration required!**
-
-Settings are stored as JSON in `system_settings` table. New fields are automatically included.
-
-## Alternative: Full Custom Frontend Approach
-
-If you need **complete branding consistency** (no LNbits UI shown), you would need to:
-
-1. Build password reset form in web-app
-2. Parse `?reset_key=` from URL
-3. Add API method to call `/api/v1/auth/reset`
-4. Handle validation, errors, loading states
-5. Update admin UI to generate links pointing to web-app
-
-This is **significantly more work** for marginal benefit (users see LNbits UI for ~5 seconds during password reset).
-
-## Recommendation
-
-**Use this simple approach** unless you have specific requirements for complete UI consistency. The brief LNbits UI is a small trade-off for the simplicity gained.
-
-## Related Files
-
-- `lnbits/settings.py` - Setting definition
-- `lnbits/helpers.py` - Expose to frontend
-- `lnbits/static/js/index.js` - Redirect logic
-
-## Example `.env`
-
-```bash
-# LNbits Configuration
-LNBITS_DATA_FOLDER=./data
-LNBITS_DATABASE_URL=sqlite:///./data/database.sqlite3
-
-# Custom Frontend Integration
-LNBITS_CUSTOM_FRONTEND_URL=https://myapp.com
-
-# Other settings...
-```
-
-## How Web-App Benefits
-
-Your web-app at `https://myapp.com` can now:
-
-1. **Receive logged-in users** from LNbits without any code changes
-2. **Use existing `auth.checkAuth()`** - it just works
-3. **Focus on your features** - don't rebuild auth UI
-4. **Trust LNbits security** - it's battle-tested
-
-The auth cookies LNbits sets are valid for your domain if LNbits is on a subdomain (e.g., `api.myapp.com`) or you're using proper CORS configuration.
-
-## Future Enhancement
-
-If you later need the full custom UI approach, all the groundwork is there:
-- Setting exists and is configurable
-- Just add the web-app UI components
-- Update admin panel to generate web-app links
-
-But start with this simple approach first! 🚀
diff --git a/Dockerfile.boltz b/Dockerfile.boltz
index 5842a537..cfd079e7 100644
--- a/Dockerfile.boltz
+++ b/Dockerfile.boltz
@@ -1,7 +1,6 @@
-ARG LNBITS_TAG=latest
-
FROM boltz/boltz-client:latest AS boltz
-FROM lnbits/lnbits:${LNBITS_TAG}
+
+FROM lnbits/lnbits:latest
COPY --from=boltz /bin/boltzd /bin/boltzcli /usr/local/bin/
RUN ls -l /usr/local/bin/boltzd
diff --git a/README.md b/README.md
index 4a34df40..b2d9c935 100644
--- a/README.md
+++ b/README.md
@@ -1,46 +1,38 @@
-
-
-
+](https://t.me/lnbits) [
](https://opensats.org)
-
-[](https://demo.lnbits.com/tipjar/DwaUiE4kBX6mUW6pj3X5Kg)
+ [![license-badge]](LICENSE) [![docs-badge]][docs]  [
](https://t.me/lnbits) [
](https://opensats.org)
+
-# LNbits — The most powerful Bitcoin & Lightning toolkit
+# The world's most powerful suite of bitcoin tools.
-> Run it for yourself, for your community, or as part of a larger stack.
+## Run for yourself, for others, or as part of a stack.
-## What is LNbits?
+LNbits is beta, for responsible disclosure of any concerns please contact an admin in the community chat.
-LNbits is a lightweight Python server that sits on top of your Lightning funding source. It gives you safe, isolated wallets, a clean API, and an extension system for rapidly adding features - without locking you into a single node implementation. The Inspiration for LNBits came from ideas pioneered by **OpenNode** and **LNPay** — both today work as funding sources for LNbits.
+LNbits is a Python server that sits on top of any funding source. It can be used as:
-## What you can do with LNbits
+- Accounts system to mitigate the risk of exposing applications to your full balance via unique API keys for each wallet
+- Extendable platform for exploring Lightning network functionality via the LNbits extension framework
+- Part of a development stack via LNbits API
+- Fallback wallet for the LNURL scheme
+- Instant wallet for LN demonstrations
-- **Harden app security:** Create per-wallet API keys so individual apps never touch your full balance.
-- **Extend functionality fast:** Install extensions to explore and ship Lightning features with minimal code.
-- **Build into your stack:** Use the LNbits HTTP API to integrate payments, wallets, and accounting.
-- **Cover LNURL flows:** Use LNbits as a reliable fallback wallet for LNURL.
-- **Demo in minutes:** Spin up instant wallets for workshops, proofs-of-concept, and user testing.
+LNbits can run on top of almost all Lightning funding sources.
-## Funding sources
+See [LNbits manual](https://docs.lnbits.org/guide/wallets.html) for more detailed documentation about each funding source.
-LNbits runs on top of most Lightning backends. Choose the one you already operate - or swap later without changing your app architecture.
+Checkout the LNbits [YouTube](https://www.youtube.com/playlist?list=PLPj3KCksGbSYG0ciIQUWJru1dWstPHshe) video series.
-- Read the [funding source guide](https://docs.lnbits.org/guide/wallets.html)
-
-## Learn more
-
-- Video series on [Youtube](https://www.youtube.com/@lnbits)
-- Introduction Video [LNBits V1](https://www.youtube.com/watch?v=PFAHKxvgI9Y&t=19s)
+LNbits is inspired by all the great work of [opennode.com](https://www.opennode.com/), and in particular [lnpay.co](https://lnpay.co/). Both work as funding sources for LNbits.
## Running LNbits
-See the [install guide](https://github.com/lnbits/lnbits/blob/main/docs/guide/installation.md) for details on installation and setup.
+Test on our demo server [demo.lnbits.com](https://demo.lnbits.com), or on [lnbits.com](https://lnbits.com) software as a service, where you can spin up an LNbits instance for 21sats per hr.
-Get yourself familiar and test on our demo server [demo.lnbits.com](https://demo.lnbits.com), or on [lnbits.com](https://lnbits.com) software as a service, where you can spin up an LNbits instance for 21sats per hr.
+See the [install guide](https://github.com/lnbits/lnbits/blob/main/docs/guide/installation.md) for details on installation and setup.
## LNbits account system
@@ -74,15 +66,9 @@ As well as working great in a browser, LNbits has native IoS and Android apps as
-## Powered by LNbits
+## Tip us
-LNbits empowers everyone with modular, open-source tools for building Bitcoin-based systems — fast, free, and extendable.
-
-[](https://shop.lnbits.com/)
-[](https://shop.lnbits.com/)
-[](https://my.lnbits.com/login)
-[](https://news.lnbits.com/)
-[](https://extensions.lnbits.com/) [](https://demo.lnbits.com/tipjar/DwaUiE4kBX6mUW6pj3X5Kg)
+If you like this project [send some tip love](https://demo.lnbits.com/lnurlp/link/fH59GD)!
[docs]: https://github.com/lnbits/lnbits/wiki
[docs-badge]: https://img.shields.io/badge/docs-lnbits.org-673ab7.svg
diff --git a/docs/_config.yml b/docs/_config.yml
index 6373311c..75ddd399 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -4,7 +4,6 @@ color_scheme: dark
logo: "/logos/lnbits-full-inverse.png"
search_enabled: true
url: https://docs.lnbits.org
-markdown: gfm
aux_links:
"LNbits on GitHub":
- "//github.com/lnbits/lnbits"
diff --git a/docs/guide/admin_ui.md b/docs/guide/admin_ui.md
index f71019a2..f732d9e5 100644
--- a/docs/guide/admin_ui.md
+++ b/docs/guide/admin_ui.md
@@ -1,134 +1,78 @@
---
layout: default
title: Admin UI
-nav_order: 1
+nav_order: 4
---
-
-
- ](https://t.me/lnbits)
-[
](https://opensats.org)
+The LNbits Admin UI lets you change LNbits settings via the LNbits frontend.
+It is disabled by default and the first time you set the environment variable `LNBITS_ADMIN_UI=true`
+the settings are initialized and saved to the database and will be used from there as long the UI is enabled.
+From there on the settings from the database are used.
-# LNBits Admin UI
+# Super User
-[What you can do](#what-you-can-do-with-the-admin-ui) · [First Run](#first-run-and-super-user-id) · [Enable/Disable](#enabling-or-disabling-the-admin-ui) · [Reset](#reset-to-defaults) · [Allowed Users](#allowed-users) · [Guides](#additional-guides)
+With the Admin UI we introduced the super user, it is created with the initialisation of the Admin UI and will be shown with a success message in the server logs.
+The super user has access to the server and can change settings that may crash the server and make it unresponsive via the frontend and api, like changing funding sources.
-**We introduced the Admin UI as the new default to make setup simpler and more straightforward**. Instead of hand editing the `.env` file, you configure key server settings directly in the frontend with clear labels and guardrails.
+Also only the super user can brrrr satoshis to different wallets.
-On a fresh install the Admin UI is enabled by default, and at first launch you are prompted to create **Super User** credentials so that sensitive operations, such as switching funding sources, remain in trusted hands. When the Admin UI is enabled, configuration is written to and read from the database; for all settings managed by the UI, the parameters in `.env` are largely no longer used. If you disable the Admin UI, the `.env` file becomes the single source of truth again.
+The super user is only stored inside the settings table of the database and after the settings are "reset to defaults" and a restart happened,
+a new super user is created.
-For privileged actions and role details see **[Super User](./super_user.md)** & [User Roles](./user_roles.md)
-For a complete reference of legacy variables consult **[.env.example](../../.env.example)**.
+The super user is never sent over the api and the frontend only receives a bool if you are super user or not.
-
+We also added a decorator for the API routes to check for super user.
-> [!WARNING]
-> Some settings remain `.env` only. Use **[.env.example](../../.env.example#L3-L87)** as the authoritative reference for those variables.
+There is also the possibility of posting the super user via webhook to another service when it is created. you can look it up here https://github.com/lnbits/lnbits/blob/main/lnbits/settings.py `class SaaSSettings`
-## What you can do with the Admin UI
+# Admin Users
-- Switch funding sources and other server level settings
-- Manage who can access LNbits (**[Allowed Users](#allowed-users)**)
-- Promote or demote Admin Users
-- Gate extensions to Admins only or disable them globally
-- Adjust balances with credit or debit
-- Adjust site customization
+environment variable: `LNBITS_ADMIN_USERS`, comma-separated list of user ids
+Admin Users can change settings in the admin ui as well, with the exception of funding source settings, because they require e server restart and could potentially make the server inaccessible. Also they have access to all the extension defined in `LNBITS_ADMIN_EXTENSIONS`.
-> [!NOTE]
-> See **[Super User](./super_user.md)** for the role and permission differences compared to Admin Users.
+# Allowed Users
-## First run and Super User ID
+environment variable: `LNBITS_ALLOWED_USERS`, comma-separated list of user ids
+By defining this users, LNbits will no longer be usable by the public, only defined users and admins can then access the LNbits frontend.
-On first start with the Admin UI enabled you will be prompted to generate a Super User.
+Setting this environment variable also disables account creation.
+Account creation can be also disabled by setting `LNBITS_ALLOW_NEW_ACCOUNTS=false`
-
+# How to activate
-If you need to read it from disk later:
+```
+$ sudo systemctl stop lnbits.service
+$ cd ~/lnbits
+$ sudo nano .env
+```
-```bash
-cat /lnbits/data/.super_user
-# example
+-> set: `LNBITS_ADMIN_UI=true`
+
+Now start LNbits once in the terminal window
+
+```
+$ uv run lnbits
+```
+
+You can now `cat` the Super User ID:
+
+```
+$ cat data/.super_user
123de4bfdddddbbeb48c8bc8382fe123
```
-> [!WARNING]
-> For security reasons, Super Users and Admin users must authenticate with credentials (username and password).
+You can access your super user account at `/wallet?usr=super_user_id`. You just have to append it to your normal LNbits web domain.
-After login you will see **Settings** and **Users** in the sidebar between **Wallets** and **Extensions**, plus a role badge in the top left.
+After that you will find the **`Admin` / `Manage Server`** between `Wallets` and `Extensions`
-
+Here you can design the interface, it has credit/debit to change wallets balances and you can restrict access rights to extensions only for admins or generally deactivated for everyone. You can make users admins or set up Allowed Users if you want to restrict access. And of course the classic settings of the .env file, e.g. to change the funding source wallet or set a charge fee.
-## Enabling or disabling the Admin UI
+Do not forget
-The Admin UI is enabled by default on new installs. To change the state:
+```
+sudo systemctl start lnbits.service
+```
-1. Stop LNbits
-
- ```bash
- sudo systemctl stop lnbits.service
- ```
-
-2. Edit your `.env`
-
- ```
- cd ~/lnbits
- sudo nano .env
- ```
-
-3. Set one of
-
- ```
- # Enable Admin UI
- LNBITS_ADMIN_UI=true
-
- # Disable Admin UI
- LNBITS_ADMIN_UI=false
- ```
-
-4. Start LNbits
-
- ```
- sudo systemctl start lnbits.service
- ```
-
-> [!NOTE]
-> With the Admin UI enabled, config is DB-backed and UI-managed settings ignore .env. Disable it to revert to [.env](../../.env.example) as the single source of truth.
-
-## Reset to defaults
-
-Using `Reset to defaults` in the Admin UI wipes stored settings. After a restart, a new `Super User` is created and the old one is no longer valid.
-
-## Allowed Users
-
-When set **at least one**, LNbits becomes private: only the listed users and Admins can access the frontend. Account creation is disabled automatically. You can also disable account creation explicitly.
-
-
-
-> [!WARNING]
-> Assign your own account first when enabling **Allowed Users** to avoid locking yourself out. If you do get locked out, use your Super User to recover access.
-
-## Additional Guides
-
-- **[Backend Wallets](./wallets.md)** — Explore options to fund your LNbits instance.
-- **[User Roles](./user_roles.md)** — Overview of existing roles in LNbits.
-- **[Funding sources](./funding-sources-table.md)** — What is available and how to configure each.
-- **[Install LNBits](./installation.md)** — Choose your prefared way to install LNBits.
-
-## Powered by LNbits
-
-LNbits empowers everyone with modular, open source tools for building Bitcoin based systems — fast, free, and extendable.
-
-If you like this project, [send some tip love](https://demo.lnbits.com/tipjar/DwaUiE4kBX6mUW6pj3X5Kg) or visit our [Shop](https://shop.lnbits.de)
-
-[](https://shop.lnbits.com/)
-[](https://shop.lnbits.com/)
-[](https://my.lnbits.com/login)
-[](https://news.lnbits.com/)
-[](https://extensions.lnbits.com/)
+A little hint, if you set `RESET TO DEFAULTS`, then a new Super User Account will also be created. The old one is then no longer valid.
diff --git a/docs/guide/amountless-invoice-implementation.md b/docs/guide/amountless-invoice-implementation.md
deleted file mode 100644
index bec96c50..00000000
--- a/docs/guide/amountless-invoice-implementation.md
+++ /dev/null
@@ -1,459 +0,0 @@
-# Amountless BOLT11 Invoice Support in LNbits
-
-This document provides a comprehensive analysis supporting the implementation of amountless (zero-amount) BOLT11 invoice payments in LNbits, with a focus on the LND REST backend.
-
-## Table of Contents
-
-- [Overview](#overview)
-- [What Are Amountless Invoices?](#what-are-amountless-invoices)
-- [Use Cases](#use-cases)
-- [Industry Analysis: Mobile Wallet Implementations](#industry-analysis-mobile-wallet-implementations)
- - [Blixt Wallet (React Native)](#blixt-wallet-react-native)
- - [Breez SDK (Flutter)](#breez-sdk-flutter)
- - [Zeus Wallet (React Native)](#zeus-wallet-react-native)
- - [Common Patterns](#common-patterns)
-- [LND API Specification](#lnd-api-specification)
- - [SendPaymentRequest Fields](#sendpaymentrequest-fields)
- - [Amountless Invoice Handling](#amountless-invoice-handling)
- - [Validation Logic](#validation-logic)
-- [LNbits Implementation](#lnbits-implementation)
- - [Architecture Overview](#architecture-overview)
- - [Layer-by-Layer Changes](#layer-by-layer-changes)
- - [API Usage](#api-usage)
-- [Verification Matrix](#verification-matrix)
-- [Security Considerations](#security-considerations)
-- [Testing](#testing)
-
----
-
-## Overview
-
-This implementation adds the ability to pay BOLT11 invoices that don't have an embedded amount by specifying the amount at payment time via the `amount_msat` parameter.
-
-**Key Changes:**
-
-- Added `Feature.amountless_invoice` to wallet base class for capability detection
-- Updated `Wallet.pay_invoice()` signature with optional `amount_msat` parameter
-- Implemented amountless invoice support in LND REST and LND gRPC wallets
-- Updated payment service layer to validate and pass through `amount_msat`
-- Added `amount_msat` field to CreateInvoice API model
-
----
-
-## What Are Amountless Invoices?
-
-A BOLT11 invoice typically encodes a specific amount to be paid. However, the BOLT11 specification allows for invoices without an amount field, leaving the payment amount to be determined by the payer. These are commonly called:
-
-- **Amountless invoices**
-- **Zero-amount invoices**
-- **Open invoices**
-
-When decoded, these invoices have `amount_msat = null` or `amount_msat = 0`.
-
----
-
-## Use Cases
-
-1. **Donations**: Accept any amount the donor wishes to give
-2. **Tips**: Allow customers to decide the tip amount
-3. **Variable services**: Pay-what-you-want pricing models
-4. **LNURL-withdraw**: Some LNURL flows use amountless invoices
-5. **NFC payments**: Tap-to-pay scenarios where amount is determined at payment time
-
----
-
-## Industry Analysis: Mobile Wallet Implementations
-
-To ensure our implementation follows established patterns, we analyzed three major Lightning mobile wallets.
-
-### Blixt Wallet (React Native)
-
-**Detection** (`src/state/Send.ts:185`):
-
-```typescript
-if (!paymentRequest.numSatoshis) {
- // Invoice is amountless - require user input
-}
-```
-
-**Amount Injection** (`src/state/Send.ts:203-204`):
-
-```typescript
-// Mutate the payment request with user-provided amount
-paymentRequest.numSatoshis = payload.amount
-```
-
-**UI Handling** (`src/windows/Send/SendConfirmation.tsx:67-70`):
-
-```typescript
-const amountEditable = !paymentRequest.numSatoshis
-// Shows editable amount field when invoice has no amount
-```
-
-**Key Pattern**: Blixt mutates the payment request object directly before sending to the LND backend.
-
-### Breez SDK (Flutter)
-
-**Detection** (`lib/widgets/payment_request_info_dialog.dart:162`):
-
-```dart
-if (widget.invoice.amount == 0) {
- // Show amount input field
-}
-```
-
-**Validation** (`lib/widgets/payment_request_info_dialog.dart:251`):
-
-```dart
-var validationResult = acc.validateOutgoingPayment(amountToPay);
-if (validationResult.isNotEmpty) {
- // Show validation error
-}
-```
-
-**Key Pattern**: Breez validates the user-entered amount against account balance before payment.
-
-### Zeus Wallet (React Native)
-
-**Detection** (`views/PaymentRequest.tsx:602-603`):
-
-```typescript
-const isNoAmountInvoice = !requestAmount || requestAmount === 0
-```
-
-**Amount Handling** (`views/Send.tsx:339-341`):
-
-```typescript
-if (isNoAmountInvoice) {
- // Use amount from user input instead of invoice
- amountToSend = userEnteredAmount
-}
-```
-
-**Key Pattern**: Zeus uses explicit boolean flags (`isNoAmountInvoice`) for clear code intent.
-
-### Common Patterns
-
-All three wallets follow the same logical flow:
-
-| Step | Pattern |
-| ----------- | -------------------------------------- |
-| 1. Decode | Parse BOLT11 invoice |
-| 2. Detect | Check if `amount == 0` or `null` |
-| 3. Prompt | Show UI for amount input if amountless |
-| 4. Validate | Verify amount > 0 and within balance |
-| 5. Inject | Pass amount to payment backend |
-| 6. Pay | Execute payment with specified amount |
-
----
-
-## LND API Specification
-
-The implementation must comply with LND's REST and gRPC API specifications.
-
-### SendPaymentRequest Fields
-
-From `lnrpc/routerrpc/router.proto`:
-
-```protobuf
-message SendPaymentRequest {
- // Number of satoshis to send.
- // The fields amt and amt_msat are mutually exclusive.
- int64 amt = 2;
-
- // A bare-bones invoice for a payment within the Lightning Network.
- // The amount in the payment request may be zero. In that case it is
- // required to set the amt field as well.
- string payment_request = 5;
-
- // Number of millisatoshis to send.
- // The fields amt and amt_msat are mutually exclusive.
- int64 amt_msat = 12;
-}
-```
-
-**Key Points:**
-
-- `amt` and `amt_msat` are mutually exclusive
-- When `payment_request` has zero amount, `amt` or `amt_msat` is **required**
-- When `payment_request` has an amount, `amt`/`amt_msat` must **not** be specified
-
-### Amountless Invoice Handling
-
-From `lnrpc/routerrpc/router_backend.go:1028-1045`:
-
-```go
-// If the amount was not included in the invoice, then we let
-// the payer specify the amount of satoshis they wish to send.
-if payReq.MilliSat == nil {
- if reqAmt == 0 {
- return nil, errors.New("amount must be specified when paying a zero amount invoice")
- }
- payIntent.Amount = reqAmt
-} else {
- if reqAmt != 0 {
- return nil, errors.New("amount must not be specified when paying a non-zero amount invoice")
- }
- payIntent.Amount = *payReq.MilliSat
-}
-```
-
-### Validation Logic
-
-LND's `UnmarshallAmt` function (`lnrpc/marshall_utils.go:57-72`):
-
-```go
-func UnmarshallAmt(amtSat, amtMsat int64) (lnwire.MilliSatoshi, error) {
- if amtSat != 0 && amtMsat != 0 {
- return 0, ErrSatMsatMutualExclusive
- }
- if amtSat < 0 || amtMsat < 0 {
- return 0, ErrNegativeAmt
- }
- if amtSat != 0 {
- return lnwire.NewMSatFromSatoshis(btcutil.Amount(amtSat)), nil
- }
- return lnwire.MilliSatoshi(amtMsat), nil
-}
-```
-
----
-
-## LNbits Implementation
-
-### Architecture Overview
-
-LNbits uses a layered architecture where changes flow from API → Service → Wallet:
-
-```
-┌─────────────────────────────────────────────────────────┐
-│ API Layer (payment_api.py) │
-│ - Receives amount_msat from client │
-└─────────────────────┬───────────────────────────────────┘
- │
-┌─────────────────────▼───────────────────────────────────┐
-│ Service Layer (payments.py) │
-│ - Validates amountless invoice + amount_msat │
-│ - Checks funding source capability │
-│ - Passes amountless_amount_msat through chain │
-└─────────────────────┬───────────────────────────────────┘
- │
-┌─────────────────────▼───────────────────────────────────┐
-│ Wallet Layer (lndrest.py, lndgrpc.py, etc.) │
-│ - Adds amt_msat to LND request if provided │
-│ - Declares Feature.amountless_invoice capability │
-└─────────────────────────────────────────────────────────┘
-```
-
-### Layer-by-Layer Changes
-
-#### 1. Base Wallet Class (`lnbits/wallets/base.py`)
-
-**Feature Declaration:**
-
-```python
-class Feature(Enum):
- nodemanager = "nodemanager"
- holdinvoice = "holdinvoice"
- amountless_invoice = "amountless_invoice" # NEW
-```
-
-**Method Signature:**
-
-```python
-@abstractmethod
-def pay_invoice(
- self, bolt11: str, fee_limit_msat: int, amount_msat: int | None = None
-) -> Coroutine[None, None, PaymentResponse]:
- """
- Pay a BOLT11 invoice.
-
- Args:
- bolt11: The BOLT11 invoice string
- fee_limit_msat: Maximum fee in millisatoshis
- amount_msat: Amount to pay in millisatoshis. Required for amountless
- invoices on wallets that support Feature.amountless_invoice.
- Ignored for invoices that already contain an amount.
- """
- pass
-```
-
-#### 2. LND REST Wallet (`lnbits/wallets/lndrest.py`)
-
-**Feature Declaration:**
-
-```python
-features = [Feature.nodemanager, Feature.holdinvoice, Feature.amountless_invoice]
-```
-
-**Payment Implementation:**
-
-```python
-async def pay_invoice(
- self, bolt11: str, fee_limit_msat: int, amount_msat: int | None = None
-) -> PaymentResponse:
- req: dict = {
- "payment_request": bolt11,
- "fee_limit_msat": fee_limit_msat,
- "timeout_seconds": 30,
- "no_inflight_updates": True,
- }
- # For amountless invoices, specify the amount to pay
- if amount_msat is not None:
- req["amt_msat"] = amount_msat
- # ... rest of implementation
-```
-
-#### 3. Payment Service (`lnbits/core/services/payments.py`)
-
-**Validation:**
-
-```python
-def _validate_payment_request(
- payment_request: str, max_sat: int | None = None, amount_msat: int | None = None
-) -> Bolt11:
- invoice = bolt11_decode(payment_request)
-
- if not invoice.amount_msat or invoice.amount_msat <= 0:
- # Amountless invoice - check capability and require amount
- funding_source = get_funding_source()
- if not funding_source.has_feature(Feature.amountless_invoice):
- raise PaymentError(
- "Amountless invoices not supported by the funding source.",
- status="failed",
- )
- if not amount_msat or amount_msat <= 0:
- raise PaymentError(
- "Amount required for amountless invoices.",
- status="failed",
- )
- check_amount_msat = amount_msat
- else:
- check_amount_msat = invoice.amount_msat
-
- # Validate against max payment limit
- # ...
-```
-
-**Amount Handling:**
-
-```python
-# Determine the actual amount to pay
-pay_amount_msat = invoice.amount_msat or amount_msat
-
-# Only pass amount to funding source if invoice is amountless
-amountless_amount_msat = amount_msat if not invoice.amount_msat else None
-```
-
-#### 4. API Layer (`lnbits/core/views/payment_api.py`)
-
-```python
-payment = await pay_invoice(
- wallet_id=wallet_id,
- payment_request=invoice_data.bolt11,
- extra=invoice_data.extra,
- labels=invoice_data.labels,
- amount_msat=invoice_data.amount_msat, # NEW
-)
-```
-
-#### 5. API Model (`lnbits/core/models/payments.py`)
-
-```python
-class CreateInvoice(BaseModel):
- # ... existing fields
- amount_msat: int | None = Query(
- None,
- ge=1,
- description=(
- "Amount to pay in millisatoshis. Required for amountless invoices "
- "when the funding source supports them."
- ),
- )
-```
-
-### API Usage
-
-**Paying an amountless invoice:**
-
-```bash
-curl -X POST "https://lnbits.example.com/api/v1/payments" \
- -H "X-Api-Key:
- ](https://t.me/lnbits)
-[
](https://opensats.org)
+There may be trade-offs between the funding sources used, for example funding LNbits using Strike requires the user to KYC themselves and has some
+privacy compromises versus running your own LND node. However the technical barrier to entry of using Strike is lower than using LND.
-# Backend Wallet Comparison Table
-
-LNbits lets you choose **how your wallets are funded** — from fully self-custodial nodes to simple hosted services. You can switch the funding source **without touching your apps, users, or extensions**. That means you can start fast, learn, and later upgrade to more control and privacy when you are ready.
-
-**Why this matters**
-
-- **Flexibility:** Pick the backend that fits your skills and constraints today, change it later with minimal friction.
-- **Speed to ship:** Use a hosted option to get live quickly; move to a node when you need more control.
-- **Scalability:** Match cost and maintenance to your stage — from hobby to production.
-- **Privacy and compliance:** Choose between self-custody and provider-managed options depending on your requirements.
-
-Below is a side-by-side comparison of Lightning funding sources you can use with LNbits.
-
-> [!NOTE]
-> “Backend Wallet” and “Funding Source” mean the same thing — the wallet or service that funds your LNbits.
+The table below offers a comparison of the different Lightning Network funding sources that can be used with LNbits.
## LNbits Lightning Network Funding Sources Comparison Table
-| **Funding Source** | **Custodial Type** | **KYC Required** | **Technical Knowledge Needed** | **Node Hosting Required** | **Privacy Level** | **Liquidity Management** | **Ease of Setup** | **Maintenance Effort** | **Cost Implications** | **Scalability** | **Notes** |
-| ------------------------------ | ------------------------ | ------------------- | ------------------------------ | ------------------------- | ----------------- | ------------------------ | ----------------- | ---------------------- | -------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------ |
-| **LND (gRPC)** | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | gRPC interface for LND; suitable for advanced integrations. |
-| **CoreLightning (CLN)** | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | Requires setting up and managing your own CLN node. |
-| **Phoenixd** | Self-custodial | ❌ | Medium | ❌ | Medium | Automatic | Moderate | Low | Minimal fees | Medium | Mobile wallet backend; suitable for mobile integrations. |
-| **Nostr Wallet Connect (NWC)** | Custodial | Depends on provider | Low | ❌ | Variable | Provider-managed | Easy | Low | May incur fees | Medium | Connects via Nostr protocol; depends on provider's policies. |
-| **Boltz** | Self-custodial | ❌ | Medium | ❌ | Medium | Provider-managed | Moderate | Moderate | Minimal fees | Medium | Uses submarine swaps; connects to Boltz client. |
-| **LND (REST)** | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | REST interface for LND; suitable for web integrations. |
-| **CoreLightning REST** | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | REST interface for CLN; suitable for web integrations. |
-| **LNbits (another instance)** | Custodial | Depends on host | Low | ❌ | Variable | Provider-managed | Easy | Low | May incur hosting fees | Medium | Connects to another LNbits instance; depends on host's policies. |
-| **Alby** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Browser extension wallet; suitable for web users. |
-| **Breez SDK** | Self-custodial | ❌ | Medium | ❌ | High | Automatic | Moderate | Low | Minimal fees | Medium | SDK for integrating Breez wallet functionalities. |
-| **OpenNode** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; suitable for merchants. |
-| **Blink** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; focuses on mobile integrations. |
-| **ZBD** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Gaming-focused payment platform. |
-| **Spark (CLN)** | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | Web interface for CLN; requires Spark server setup. |
-| **Cliche Wallet** | Self-custodial | ❌ | Medium | ❌ | Medium | Manual | Moderate | Moderate | Minimal fees | Medium | Lightweight wallet; suitable for embedded systems. |
-| **Strike** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; suitable for quick setups. |
-| **LNPay** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; suitable for quick setups. |
-| **Eclair (ACINQ)** | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | Connects via API; you run and manage your Eclair node. |
-| **LN.tips** | Custodial/Self-Custodial | Depends on provider | Medium | ❌ | Low | Provider-managed | Moderate | Low | Transaction fees may apply | Medium | Simple hosted service; use LN.tips API as your backend. |
-| **Fake Wallet** | Testing (simulated) | ❌ | Low | ❌ | N/A | N/A | Easy | Low | None (test only) | N/A | For testing only; mints accounting units in LNbits (no real sats, unit name configurable). |
-
----
-
-### Notes for readers
-
-- These are typical characteristics; your exact experience may vary by configuration and provider policy.
-- Pick based on your constraints: compliance (KYC), privacy, ops effort, and time-to-ship.
-
----
-
-## Additional Guides
-
-- **[Admin UI](./admin_ui.md)** — Manage server settings via a clean UI (avoid editing `.env` by hand).
-- **[User Roles](./User_Roles.md)** — Quick Overview of existing Roles in LNBits.
-- **[Funding sources](./funding-sources_table.md)** — What’s available and how to enable/configure each.
-
-## Powered by LNbits
-
-LNbits empowers everyone with modular, open-source tools for building Bitcoin-based systems — fast, free, and extendable.
-
-If you like this project, [send some tip love](https://demo.lnbits.com/tipjar/DwaUiE4kBX6mUW6pj3X5Kg) or visit our [Shop](https://shop.lnbits.de)
-
-[](https://shop.lnbits.com/)
-[](https://shop.lnbits.com/)
-[](https://my.lnbits.com/login)
-[](https://news.lnbits.com/)
-[](https://extensions.lnbits.com/)
+| **Funding Source** | **Custodial Type** | **KYC Required** | **Technical Knowledge Needed** | **Node Hosting Required** | **Privacy Level** | **Liquidity Management** | **Ease of Setup** | **Maintenance Effort** | **Cost Implications** | **Scalability** | **Notes** |
+| -------------------------- | ------------------ | ------------------- | ------------------------------ | ------------------------- | ----------------- | ------------------------ | ----------------- | ---------------------- | -------------------------------------------- | --------------- | ---------------------------------------------------------------- |
+| LND (gRPC) | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | gRPC interface for LND; suitable for advanced integrations. |
+| CoreLightning (CLN) | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | Requires setting up and managing your own CLN node. |
+| Phoenixd | Self-custodial | ❌ | Medium | ❌ | Medium | Automatic | Moderate | Low | Minimal fees | Medium | Mobile wallet backend; suitable for mobile integrations. |
+| Nostr Wallet Connect (NWC) | Custodial | Depends on provider | Low | ❌ | Variable | Provider-managed | Easy | Low | May incur fees | Medium | Connects via Nostr protocol; depends on provider's policies. |
+| Boltz | Self-custodial | ❌ | Medium | ❌ | Medium | Provider-managed | Moderate | Moderate | Minimal fees | Medium | Uses submarine swaps; connects to Boltz client. |
+| LND (REST) | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | REST interface for LND; suitable for web integrations. |
+| CoreLightning REST | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | REST interface for CLN; suitable for web integrations. |
+| LNbits (another instance) | Custodial | Depends on host | Low | ❌ | Variable | Provider-managed | Easy | Low | May incur hosting fees | Medium | Connects to another LNbits instance; depends on host's policies. |
+| Alby | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Browser extension wallet; suitable for web users. |
+| Breez SDK | Self-custodial | ❌ | Medium | ❌ | High | Automatic | Moderate | Low | Minimal fees | Medium | SDK for integrating Breez wallet functionalities. |
+| OpenNode | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; suitable for merchants. |
+| Blink | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; focuses on mobile integrations. |
+| ZBD | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Gaming-focused payment platform. |
+| Spark (CLN) | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | Web interface for CLN; requires Spark server setup. |
+| Cliche Wallet | Self-custodial | ❌ | Medium | ❌ | Medium | Manual | Moderate | Moderate | Minimal fees | Medium | Lightweight wallet; suitable for embedded systems. |
+| Strike | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; suitable for quick setups. |
+| LNPay | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; suitable for quick setups. |
diff --git a/docs/guide/installation.md b/docs/guide/installation.md
index 4e4e08b6..cbe8d7a4 100644
--- a/docs/guide/installation.md
+++ b/docs/guide/installation.md
@@ -1,51 +1,18 @@
---
layout: default
-title: Installation
-nav_order: 1
+title: Basic installation
+nav_order: 2
---
-
-
- ](https://t.me/lnbits)
-
# Basic installation
-> [!NOTE]
-> **Default DB:** LNbits uses SQLite by default (simple & effective). You can switch to PostgreSQL — see the section below.
+Note that by default LNbits uses SQLite as its database, which is simple and effective but you can configure it to use PostgreSQL instead which is also described in a section below.
-## Table of contents
+## Option 1: AppImage (LInux)
-- [Option 1: AppImage (Linux)](#option-1-appimage-linux)
-- [Option 2: UV (recommended for developers)](#option-2-uv-recommended-for-developers)
-- [Option 2a (Legacy): Poetry — Replaced by UV](#option-2a-legacy-poetry--replaced-by-uv)
-- [Option 3: Install script (Debian/Ubuntu)](#option-3-install-script-debianubuntu)
-- [Option 4: Nix](#option-4-nix)
-- [Option 5: Docker](#option-5-docker)
-- [Option 6: Fly.io](#option-6-flyio)
-- [Troubleshooting](#troubleshooting)
-- [Optional: PostgreSQL database](#optional-postgresql-database)
-- [Using LNbits](#using-lnbits)
-- [Additional guides](#additional-guides)
- - [Update LNbits (all methods)](#update-lnbits-all-methods)
- - [SQLite → PostgreSQL migration](#sqlite--postgresql-migration)
- - [LNbits as a systemd service](#lnbits-as-a-systemd-service)
- - [Reverse proxy with automatic HTTPS (Caddy)](#reverse-proxy-with-automatic-https-caddy)
- - [Apache2 reverse proxy over HTTPS](#apache2-reverse-proxy-over-https)
- - [Nginx reverse proxy over HTTPS](#nginx-reverse-proxy-over-https)
- - [HTTPS without a reverse proxy (self-signed)](#https-without-a-reverse-proxy-self-signed)
- - [LNbits on Umbrel behind Tor](#lnbits-on-umbrel-behind-tor)
- - [FreeBSD notes](#freebsd-notes)
+### AppImage (Linux)
-## Option 1: AppImage (Linux)
-
-**Quickstart**
-
-1. Download latest AppImage from [releases](https://github.com/lnbits/lnbits/releases) **or** run:
+Go to [releases](https://github.com/lnbits/lnbits/releases) and pull latest AppImage, or:
```sh
sudo apt-get install jq libfuse2
@@ -54,19 +21,19 @@ chmod +x LNbits-latest.AppImage
LNBITS_ADMIN_UI=true HOST=0.0.0.0 PORT=5000 ./LNbits-latest.AppImage # most system settings are now in the admin UI, but pass additional .env variables here
```
-- LNbits will create a folder for DB and extension files **in the same directory** as the AppImage.
-
-> [!NOTE]
-> **Next steps**
-> Install complete → **[Running LNbits](#run-the-server)**
-> Update LNBits → **[Update LNbits (all methods)](#update-lnbits-all-methods)**
+LNbits will create a folder for db and extension files in the folder the AppImage runs from.
## Option 2: UV (recommended for developers)
-> [!IMPORTANT]
-> **It is recommended to use the latest version of UV & Make sure you have Python version 3.12 installed.**
+It is recommended to use the latest version of UV. Make sure you have Python version `3.12` installed.
-### Verify Python
+### Install Python 3.12
+
+## Option 2 (recommended): UV
+
+It is recommended to use the latest version of UV. Make sure you have Python version 3.10 or higher installed.
+
+### Verify Python version
```sh
python3 --version
@@ -79,86 +46,26 @@ curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
```
-### Install LNbits
-
-```sh
-git clone https://github.com/lnbits/lnbits.git
-cd lnbits
-git checkout main
-uv sync --all-extras
-
-cp .env.example .env
-# Optional: set funding source and other options in .env (e.g., `nano .env`)
-```
-
-### Run the server
-
-```sh
-uv run lnbits
-# To change port/host: uv run lnbits --port 9000 --host 0.0.0.0
-# Add --debug to the command above and set DEBUG=true in .env for verbose output
-```
-
-### LNbits CLI
-
-```sh
-# Useful for superuser ID, updating extensions, etc.
-uv run lnbits-cli --help
-```
-
-### Update LNbits
-
-```sh
-cd lnbits
-# Stop LNbits with Ctrl + X or your service manager
-# sudo systemctl stop lnbits
-
-# Update code
-git pull --rebase
-
-uv sync --all-extras
-uv run lnbits
-```
-
-#### Use Admin UI → Extensions → "Update All" to bring extensions up to the proper level
-
-> [!NOTE]
-> **Next steps**
-> Install complete → **[Running LNbits](#run-the-server)**
-> Update LNBits → **[Update LNbits (all methods)](#update-lnbits-all-methods)**
-
-## Option 2a (Legacy): Poetry — _Replaced by UV_
-
-
Poetry install and update (legacy workflow)
-
-This legacy section is preserved for older environments.
-**UV is the recommended (and faster) tool** for new installs. Use Poetry only if you have personal preferences or must support an older workflow.
-
-> 
-> **It is recommended to use the latest version of Poetry & Make sure you have Python version 3.12 installed.**
-
-### Verify Python version
-
-```sh
-python3 --version
-```
-
-### Install Poetry
+### (old) Install Poetry
```sh
# If path 'export PATH="$HOME/.local/bin:$PATH"' fails, use the path echoed by the install
-curl -sSL https://install.python-poetry.org | python3 - && export PATH="$HOME/.local/bin:$PATH"
+curl -sSL https://install.python-poetry.org | python3 -
+export PATH="$HOME/.local/bin:$PATH"
```
-### Install LNbits
+### install LNbits
```sh
git clone https://github.com/lnbits/lnbits.git
cd lnbits
-poetry env use 3.12
git checkout main
-poetry install --only main
+uv sync --all-extras
+
+# or poetry
+# poetry env use 3.12
+# poetry install --only main
+
cp .env.example .env
# Optional: to set funding source amongst other options via the env `nano .env`
```
@@ -166,53 +73,50 @@ cp .env.example .env
#### Running the server
```sh
-poetry run lnbits
-# To change port/host: poetry run lnbits --port 9000 --host 0.0.0.0
-# Add --debug to help troubleshooting (also set DEBUG=true in .env)
+uv run lnbits
+# To change port/host pass 'uv run lnbits --port 9000 --host 0.0.0.0'
+
+# or poetry
+# poetry run lnbits
+# adding --debug in the start-up command above to help your troubleshooting and generate a more verbose output
+# Note that you have to add the line DEBUG=true in your .env file, too.
```
-#### LNbits CLI
+#### LNbits-cli
```sh
-# A very useful terminal client for getting the superuser ID, updating extensions, etc.
-poetry run lnbits-cli --help
+# A very useful terminal client for getting the supersuer ID, updating extensions, etc
+uv run lnbits-cli --help
```
#### Updating the server
```sh
cd lnbits
-# Stop LNbits with Ctrl + X or with your service manager
+# Stop LNbits with `ctrl + x` or with service manager
# sudo systemctl stop lnbits
# Update LNbits
git pull --rebase
-# Check your Poetry Python version
-poetry env list
-# If version is less than 3.12, update it:
-poetry env use python3.12
-poetry env remove python3.X
-poetry env list
+# Check your poetry version with
+# poetry env list
+# If version is less 3.12, update it by running
+# poetry env use python3.12
+# poetry env remove python3.9
+# poetry env list
-# Reinstall and start
-poetry install --only main
-poetry run lnbits
+# Run install and start LNbits with
+# poetry install --only main
+# poetry run lnbits
+
+uv sync --all-extras
+uv run lnbits
+
+# use LNbits admin UI Extensions page function "Update All" do get extensions onto proper level
```
-#### Use Admin UI → Extensions → "Update All" to bring extensions up to the proper level
-
-> 
-> **Next steps**
-> Install complete → **[Running LNbits](#run-the-server)**
-> Update LNBits → **[Update LNbits (all methods)](#update-lnbits-all-methods)**
-
-Show install script (one-line setup)
+## Option 2: Install script (on Debian/Ubuntu)
```sh
wget https://raw.githubusercontent.com/lnbits/lnbits/main/lnbits.sh &&
@@ -220,19 +124,11 @@ chmod +x lnbits.sh &&
./lnbits.sh
```
-- You can use `./lnbits.sh` to run, but for more control: `cd lnbits` and use `uv run lnbits` (see Option 2).
+Now visit `0.0.0.0:5000` to make a super-user account.
-> 
-> **Next steps**
-> Install complete → **[Running LNbits](#run-the-server)**
-> Update LNBits → **[Update LNbits (all methods)](#update-lnbits-all-methods)**
+`./lnbits.sh` can be used to run, but for more control `cd lnbits` and use `uv run lnbits` (see previous option).
-Show Nix instructions (flakes, cachix, run)
+## Option 3: Nix
```sh
# Install nix. If you have installed via another manager, remove and use this install (from https://nixos.org/download)
@@ -291,36 +187,26 @@ LNBITS_ADMIN_UI=true ./result/bin/lnbits --port 9000 --host 0.0.0.0
SUPER_USER=be54db7f245346c8833eaa430e1e0405 LNBITS_ADMIN_UI=true ./result/bin/lnbits --port 9000
```
-> 
-> **Next steps**
-> Update LNBits → **[Update LNbits (all methods)](#update-lnbits-all-methods)**
+## Option 4: Docker
-Show Docker instructions (official image, volumes, extensions)
-
-**Use latest image**
+Use latest version from Docker Hub.
```sh
docker pull lnbits/lnbits
wget https://raw.githubusercontent.com/lnbits/lnbits/main/.env.example -O .env
mkdir data
-docker run --detach --publish 5000:5000 --name lnbits \
- --volume ${PWD}/.env:/app/.env \
- --volume ${PWD}/data/:/app/data \
- lnbits/lnbits
+docker run --detach --publish 5000:5000 --name lnbits --volume ${PWD}/.env:/app/.env --volume ${PWD}/data/:/app/data lnbits/lnbits
```
-- The LNbits Docker image ships **without any extensions**; by default, any extensions you install are stored **inside the container** and will be **lost** when the container is removed, so you should set `LNBITS_EXTENSIONS_PATH` to a directory that’s **mapped to a persistent host volume** so extensions **survive rebuilds/recreates**—for example:
+The LNbits Docker image comes with no extensions installed. User-installed extensions will be stored by default in a container directory.
+It is recommended to point the `LNBITS_EXTENSIONS_PATH` environment variable to a directory that is mapped to a Docker volume. This way, the extensions will not be reinstalled when the container is destroyed.
+Example:
```sh
docker run ... -e "LNBITS_EXTENSIONS_PATH='/app/data/extensions'" --volume ${PWD}/data/:/app/data ...
```
-**Build image yourself**
+Build the image yourself.
```sh
git clone https://github.com/lnbits/lnbits.git
@@ -328,39 +214,24 @@ cd lnbits
docker build -t lnbits/lnbits .
cp .env.example .env
mkdir data
-docker run --detach --publish 5000:5000 --name lnbits \
- --volume ${PWD}/.env:/app/.env \
- --volume ${PWD}/data/:/app/data \
- lnbits/lnbits
+docker run --detach --publish 5000:5000 --name lnbits --volume ${PWD}/.env:/app/.env --volume ${PWD}/data/:/app/data lnbits/lnbits
```
-You can optionally override the install extras for both **Poetry** and **UV** to include optional features during build or setup:
-
-- with Poetry, pass extras via the `POETRY_INSTALL_ARGS` Docker build-arg (e.g., to enable the **Breez** funding source: `docker build --build-arg POETRY_INSTALL_ARGS="-E breez" -t lnbits/lnbits .`);
-- with UV, enable extras during environment sync (e.g., locally run `uv sync --extra breez` or `uv sync --all-extras`), and—**if your Dockerfile supports it**—you can mirror the same at build time via a build-arg such as `UV_SYNC_ARGS` (example pattern: `docker build --build-arg UV_SYNC_ARGS="--extra breez" -t lnbits/lnbits .`).
-
-**Enable Breez funding source at build**
+You can optionally override the arguments that are passed to `poetry install` during the build process by setting the Docker build argument named `POETRY_INSTALL_ARGS`. For example, to enable the Breez funding source, build the Docker image with the command:
```sh
docker build --build-arg POETRY_INSTALL_ARGS="-E breez" -t lnbits/lnbits .
```
-> 
-> **Next steps**
-> Install complete → **[Running LNbits](#run-the-server)**
-> Update LNBits → **[Update LNbits (all methods)](#update-lnbits-all-methods)**
+## Option 5: Fly.io
-Deploy LNbits on Fly.io (free tier friendly)
+Then, install the Fly.io CLI onto your device [here](https://fly.io/docs/getting-started/installing-flyctl/).
-**Fly.io is a docker container hosting platform that has a generous free tier. You can host LNbits for free on Fly.io for personal use.**
-
-1. Create an account at [Fly.io](https://fly.io).
-2. Install the Fly.io CLI ([guide](https://fly.io/docs/getting-started/installing-flyctl/)).
+After install is complete, the command will output a command you should copy/paste/run to get `fly` into your `$PATH`. Something like:
```
flyctl was installed successfully to /home/ubuntu/.fly/bin/flyctl
@@ -369,9 +240,9 @@ Manually add the directory to your $HOME/.bash_profile (or similar)
export PATH="$FLYCTL_INSTALL/bin:$PATH"
```
-3. You can either run those commands, then `source ~/.bash_profile` or, if you don't, you'll have to call Fly from `~/.fly/bin/flyctl`.
+You can either run those commands, then `source ~/.bash_profile` or, if you don't, you'll have to call Fly from `~/.fly/bin/flyctl`.
-- Once installed, run the following commands.
+Once installed, run the following commands.
```
git clone https://github.com/lnbits/lnbits.git
@@ -385,16 +256,9 @@ You'll be prompted to enter an app name, region, postgres (choose no), deploy no
You'll now find a file in the directory called `fly.toml`. Open that file and modify/add the following settings.
-> 
-> Be sure to replace `${PUT_YOUR_LNBITS_ENV_VARS_HERE}` with all relevant environment variables in `.env` or `.env.example`.
-> Environment variable strings should be quoted here. For example, if `.env` has
-> `LNBITS_ENDPOINT=https://demo.lnbits.com`, then in `fly.toml` use
-> `LNBITS_ENDPOINT="https://demo.lnbits.com"`.
+Note: Be sure to replace `${PUT_YOUR_LNBITS_ENV_VARS_HERE}` with all relevant environment variables in `.env` or `.env.example`. Environment variable strings should be quoted here, so if in `.env` you have `LNBITS_ENDPOINT=https://demo.lnbits.com` in `fly.toml` you should have `LNBITS_ENDPOINT="https://demo.lnbits.com"`.
-> 
-> Don't enter secret environment variables here. Fly.io offers **secrets** (via `fly secrets`) that are exposed as env vars at runtime.
-> Example (LND REST funding source):
-> `fly secrets set LND_REST_MACAROON=UV (recommended)
-
-```sh
-cd lnbits
-git pull --rebase
-uv sync --all-extras
-# restart (dev)
-uv run lnbits
-```
-
-Poetry (legacy)
-
-```sh
-cd lnbits
-git pull --rebase
-# Optional: ensure Python 3.12
-poetry env list
-poetry env use python3.12
-poetry install --only main
-# restart (dev)
-poetry run lnbits
-```
-
-AppImage
-
-Download the latest AppImage from Releases and replace your old file **in the same directory** to keep the `./data` folder (DB, extensions).
-
-Install script (Debian/Ubuntu)
-
-```sh
-# If you installed via lnbits.sh:
-cd lnbits
-git pull --rebase
-# then use your chosen runner (UV recommended)
-uv sync --all-extras
-uv run lnbits
-```
-
-Nix
-
-```sh
-cd lnbits
-git pull --rebase
-nix build
-# restart
-nix run
-```
-
-Docker (official image)
-
-```sh
-docker pull lnbits/lnbits
-docker stop lnbits && docker rm lnbits
-docker run --detach --publish 5000:5000 --name lnbits \
- --volume ${PWD}/.env:/app/.env \
- --volume ${PWD}/data/:/app/data \
- lnbits/lnbits
-```
-
-Docker (build yourself)
-
-```sh
-cd lnbits
-git pull --rebase
-docker build -t lnbits/lnbits .
-docker stop lnbits && docker rm lnbits
-docker run --detach --publish 5000:5000 --name lnbits \
- --volume ${PWD}/.env:/app/.env \
- --volume ${PWD}/data/:/app/data \
- lnbits/lnbits
-```
-
-Fly.io
-
-```sh
-# If using Dockerfile in repo (recommended)
-cd lnbits
-git pull --rebase
-fly deploy
-# Logs & shell if needed
-fly logs
-fly ssh console
-```
-
-
- ](https://t.me/lnbits)
-[
](https://opensats.org)
-
-# LNbits Super User (SU)
-
-**Table of Contents**
-
-- [What is the Super User?](#what-is-the-super-user)
-- [When is the Super User created?](#when-is-the-super-user-created)
-- [Disabeling the Admin UI](#disabeling-the-admin-ui)
-- [Super User identity and storage](#super-user-identity-and-storage)
-- [Security model since v1](#security-model-since-v1)
-- [Admin vs Super User](#admin-vs-super-user)
-- [Operational guidance](#operational-guidance)
-- [Additional guides](#additional-guides)
-
-
TLDR
-
-- **No Admin UI → No Super User.** The Super User (SU) exists only when `LNBITS_ADMIN_UI=true`.
-- **Why SU exists:** SU can do a few high impact actions regular admins cannot, like **changing the funding source**, **restarting the server from the UI**, and **crediting or debiting accounts**.
-- **Login changes since v1:** Logging in by **user ID** for SU and admins is **disabled**. On first visit after enabling the Admin UI you will be prompted to set a **username and password** for the SU.
-- **Trust model:** Admins and the SU share about **99 percent of the same powers**, but the SU is the one trusted with funding source control and cannot be demoted by regular admins.
-
-
- ](https://t.me/lnbits)
-[
](https://opensats.org)
-
-# LNbits Roles: A Quick Overview
-
-### Understand **who can do what** in seconds: `Super User`, `Admin`, and `Regular User`.
-
-**Jump to:**
-[Roles at a Glance](#roles-at-a-glance) •
-[Super User](#super-user--master-control) •
-[Admin](#admin--day-to-day-manager) •
-[Regular User](#regular-user--everyday-use) •
-[Best Practices](#best-practices) •
-[Additional Guides](#additional-guides)
-
----
-
-## Roles at a Glance
-
-| Capability | **Super User** (owner) | **Admin** (manager) | **Regular User** (end user) |
-| -------------------------------- | :--------------------: | :-----------------: | :-------------------------: |
-| Change **funding source** | ✅ | ❌ | ❌ |
-| Credit/Debit any wallet | ✅ | ❌ | ❌ |
-| Manage Admins & Users | ✅ | ✅ | ❌ |
-| Enable/disable extensions | ✅ | ✅ | ❌ |
-| Use wallets & allowed extensions | ✅ | ✅ | ✅ |
-
-> **Plain talk:** **Super User** = Owner • **Admin** = Trusted manager • **Regular User** = End user
-
-## Role Snapshots
-
-### Super User — Master Control
-
-For initial setup and rare, high-impact changes.
-
-- Configure **server-level settings** (e.g., funding source).
-- **Credit/Debit** any wallet.
-- Create and manage initial **Admin(s)**.
-
-> **Sign-in:** username + password (v1+). The old query-string login is retired.
-
-### Admin — Day-to-Day Manager
-
-For running the service without touching the most sensitive knobs.
-
-- Manage **Users**, **Admins**, and **Extensions** in the Admin UI.
-- Adjust security-related settings (e.g., `rate_limiter`, `ip_blocker`).
-- Handle operations settings (e.g., `service_fee`, `invoice_expiry`).
-- Build brand design in **Site Customization**.
-- Update user accounts.
-
-**Typical tasks:** onboarding users, enabling extensions, tidying wallets, reviewing activity.
-
-> **Sign-in:** username + password (v1+). The old query-string login is retired.
-
-### Regular User — Everyday Use
-
-For using LNbits, not administering it.
-
-- Access **personal wallets** and **allowed extensions**.
-- No server/admin privileges.
-
-**Typical tasks:** receive and send payments, use enabled extensions.
-
-## Best Practices
-
-- **Minimize risk:** Reserve **Super User** for rare, sensitive actions (funding source, debit/credit). Use **Admin** for daily operations.
-- **Keep access tidy:** Review your Admin list occasionally; remove unused accounts.
-- **Change management:** Test risky changes (like funding) in a staging setup first.
-
-## Additional Guides
-
-- **[Admin UI](./admin_ui.md)** — Manage server settings via a clean UI (avoid editing `.env` by hand).
-- **[Super User](./super_user.md)** — Deep dive on responsibilities and safe usage patterns.
-- **[Funding sources](./funding-sources-table.md)** — What’s available and how to enable/configure each.
-
-## Powered by LNbits
-
-LNbits empowers everyone with modular, open-source tools for building Bitcoin-based systems—fast, free, and extendable.
-
-If you like this project, [send some tip love](https://demo.lnbits.com/tipjar/DwaUiE4kBX6mUW6pj3X5Kg) or visit our [Shop](https://shop.lnbits.de)
-
-[](https://shop.lnbits.com/)
-[](https://shop.lnbits.com/)
-[](https://my.lnbits.com/login)
-[](https://news.lnbits.com/)
-[](https://extensions.lnbits.com/)
diff --git a/docs/guide/wallets.md b/docs/guide/wallets.md
index 51275a5e..00f5d5ef 100644
--- a/docs/guide/wallets.md
+++ b/docs/guide/wallets.md
@@ -4,367 +4,177 @@ title: Backend wallets
nav_order: 3
---
-
-
- ](https://t.me/lnbits)
-[
](https://opensats.org)
-
# Backend wallets
-**LNbits is modular**: You can switch the funding source (backend wallet) **without changing anything else** in your setup. Keep your extensions, apps, users, and config as-is — just point LNbits to a different backend via environment variables.
+LNbits can run on top of many Lightning Network funding sources with more being added regularly.
-**What stays the same when you switch backends**
+A backend wallet can be configured using the following LNbits environment variables:
-- Your LNbits setup and extensions
-- Your API keys and endpoints
-- Your server and deployment setup
-
-A backend wallet is selected and configured entirely through LNbits environment variables. See the options and variables below, and compare them here: [Funding-Source-Table.md](funding-sources-table.md)
-
-> [!NOTE]
-> **Terminology:** “Backend Wallet” and “Funding Source” mean the same thing — the wallet or service that funds your LNbits.
-
-## Funding Sources
-
-## Funding Sources
-
-| | | |
-| ----------------------------------------------- | ------------------------------------- | ------------------------------------------------- |
-| [CLNRest (runes)](#clnrest-runes) | [LND (REST)](#lnd-rest) | [OpenNode](#opennode) |
-| [CoreLightning](#corelightning) | [LND (gRPC)](#lnd-grpc) | [Blink](#blink) |
-| [CoreLightning REST](#corelightning-rest) | [LNbits](#lnbits) | [Alby](#alby) |
-| [Spark (Core Lightning)](#spark-core-lightning) | [LNPay](#lnpay) | [Boltz](#boltz) |
-| [Cliche Wallet](#cliche-wallet) | [ZBD](#zbd) | [Phoenixd](#phoenixd) |
-| [Breez SDK](#breez-sdk) | [Breez Liquid SDK](#breez-liquid-sdk) | [Nostr Wallet Connect](#nostr-wallet-connect-nwc) |
-| [Strike](#strike) | [Eclair (ACINQ)](#eclair-acinq) | [LN.tips](#lntips) |
-| [Fake Wallet](#fake-wallet) | | |
-
----
-
-
+You can [compare the LNbits compatible Lightning Network funding sources here](wallets.md).
### CLNRest (using [runes](https://docs.corelightning.org/reference/lightning-createrune))
-[Core Lightning REST API docs](https://docs.corelightning.org/docs/rest)
+[Core lightning Rest API docs](https://docs.corelightning.org/docs/rest)
+
Should also work with the [Rust version of CLNRest](https://github.com/daywalker90/clnrest-rs)
-**Environment variables**
-
-- `LNBITS_BACKEND_WALLET_CLASS`: `CLNRestWallet`
+- `LNBITS_BACKEND_WALLET_CLASS`: **CLNRestWallet**
- `CLNREST_URL`: `https://127.0.0.1:3010`
-- `CLNREST_CA`: `/home/lightningd/.lightning/bitcoin/ca.pem` (or the content of the file)
-- `CLNREST_CERT`: `/home/lightningd/.lightning/bitcoin/server.pem` (or the content of the file)
-- `CLNREST_LAST_PAY_INDEX`: `lightning-cli listinvoices | jq -r '.invoices | map(.created_index) | max'`
+- `CLNREST_CA`: `/home/lightningd/.lightning/bitcoin/ca.pem` (or the content of the `ca.pem` file)
+- `CLNREST_CERT`: `/home/lightningd/.lightning/bitcoin/server.pem` (or the content of the `server.pem` file)
+- `CLNREST_READONLY_RUNE`: `lightning-cli createrune restrictions='[["method=listfunds", "method=listpays", "method=listinvoices", "method=getinfo", "method=summary", "method=waitanyinvoice"]]' | jq -r .rune`
+- `CLNREST_INVOICE_RUNE`: `lightning-cli createrune restrictions='[["method=invoice"], ["pnameamount_msat<1000001"], ["pnamelabel^LNbits"], ["rate=60"]]' | jq -r .rune`
+- `CLNREST_PAY_RUNE`: `lightning-cli createrune restrictions='[["method=pay"], ["pinvbolt11_amount<1001"], ["pnamelabel^LNbits"], ["rate=1"]]' | jq -r .rune`
+- `CLNREST_RENEPAY_RUNE`: `lightning-cli createrune restrictions='[["method=renepay"], ["pinvinvstring_amount<1001"], ["pnamelabel^LNbits"], ["rate=1"]]' | jq -r .rune`
+- `CLNREST_LAST_PAY_INDEX`: `lightning-cli listinvoices | jq -r '.invoices | map(.created_index) | max' `
- `CLNREST_NODEID`: `lightning-cli getinfo | jq -r .id` (only required for v23.08)
-**Create runes (copy/paste)**
+### CoreLightning
-```bash
-# Read-only: funds, pays, invoices, info, summary, and invoice listener
-lightning-cli createrune \
- restrictions='[["method=listfunds","method=listpays","method=listinvoices","method=getinfo","method=summary","method=waitanyinvoice"]]' \
-| jq -r .rune
-```
+- `LNBITS_BACKEND_WALLET_CLASS`: **CoreLightningWallet**
+- `CORELIGHTNING_RPC`: /file/path/lightning-rpc
-```bash
-# Invoice: max 1,000,001 msat, label must start with "LNbits", 60 req/min
-lightning-cli createrune \
- restrictions='[["method=invoice"], ["pnameamount_msat<1000001"], ["pnamelabel^LNbits"], ["rate=60"]]' \
-| jq -r .rune
-```
+### CoreLightning REST
-```bash
-# Pay: bolt11 amount < 1001 (msat), label must start with "LNbits", 1 req/min
-lightning-cli createrune \
- restrictions='[["method=pay"], ["pinvbolt11_amount<1001"], ["pnamelabel^LNbits"], ["rate=1"]]' \
-| jq -r .rune
-```
+This is the old REST interface that uses [Ride The Lightning/c-lightning-REST](https://github.com/Ride-The-Lightning/c-lightning-REST)
-```bash
-# Renepay: invstring amount < 1001 (msat), label must start with "LNbits", 1 req/min
-lightning-cli createrune \
- restrictions='[["method=renepay"], ["pinvinvstring_amount<1001"], ["pnamelabel^LNbits"], ["rate=1"]]' \
-| jq -r .rune
-```
+- `LNBITS_BACKEND_WALLET_CLASS`: **CoreLightningRestWallet**
+- `CORELIGHTNING_REST_URL`: http://127.0.0.1:8185/
+- `CORELIGHTNING_REST_MACAROON`: /file/path/admin.macaroon or Base64/Hex
+- `CORELIGHTNING_REST_CERT`: /home/lightning/clnrest/tls.cert
-Set the resulting values into:
+### Spark (Core Lightning)
-- `CLNREST_READONLY_RUNE`
-- `CLNREST_INVOICE_RUNE`
-- `CLNREST_PAY_RUNE`
-- `CLNREST_RENEPAY_RUNE`
+- `LNBITS_BACKEND_WALLET_CLASS`: **SparkWallet**
+- `SPARK_URL`: http://10.147.17.230:9737/rpc
+- `SPARK_TOKEN`: secret_access_key
-## CoreLightning
+### LND (REST)
-**Required env vars**
+- `LNBITS_BACKEND_WALLET_CLASS`: **LndRestWallet**
+- `LND_REST_ENDPOINT`: http://10.147.17.230:8080/
+- `LND_REST_CERT`: /file/path/tls.cert
+- `LND_REST_MACAROON`: /file/path/admin.macaroon or Base64/Hex
-- `LNBITS_BACKEND_WALLET_CLASS`: `CoreLightningWallet`
-- `CORELIGHTNING_RPC`: `/file/path/lightning-rpc`
+or
-## CoreLightning REST
+- `LND_REST_MACAROON_ENCRYPTED`: eNcRyPtEdMaCaRoOn
-Old REST interface using [RTL c-lightning-REST](https://github.com/Ride-The-Lightning/c-lightning-REST)
+### LND (gRPC)
-**Required env vars**
+- `LNBITS_BACKEND_WALLET_CLASS`: **LndWallet**
+- `LND_GRPC_ENDPOINT`: ip_address
+- `LND_GRPC_PORT`: port
+- `LND_GRPC_CERT`: /file/path/tls.cert
+- `LND_GRPC_MACAROON`: /file/path/admin.macaroon or Base64/Hex
-- `LNBITS_BACKEND_WALLET_CLASS`: `CoreLightningRestWallet`
-- `CORELIGHTNING_REST_URL`: `http://127.0.0.1:8185/`
-- `CORELIGHTNING_REST_MACAROON`: `/file/path/admin.macaroon` or Base64/Hex
-- `CORELIGHTNING_REST_CERT`: `/home/lightning/clnrest/tls.cert`
+You can also use an AES-encrypted macaroon (more info) instead by using
-## Spark (Core Lightning)
+- `LND_GRPC_MACAROON_ENCRYPTED`: eNcRyPtEdMaCaRoOn
-**Required env vars**
+To encrypt your macaroon, run `uv run lnbits-cli encrypt macaroon`.
-- `LNBITS_BACKEND_WALLET_CLASS`: `SparkWallet`
-- `SPARK_URL`: `http://10.147.17.230:9737/rpc`
-- `SPARK_TOKEN`: `secret_access_key`
+### LNbits
-## LND (REST)
+- `LNBITS_BACKEND_WALLET_CLASS`: **LNbitsWallet**
+- `LNBITS_ENDPOINT`: e.g. https://lnbits.com
+- `LNBITS_KEY`: lnbitsAdminKey
-**Required env vars**
+### LNPay
-- `LNBITS_BACKEND_WALLET_CLASS`: `LndRestWallet`
-- `LND_REST_ENDPOINT`: `http://10.147.17.230:8080/`
-- `LND_REST_CERT`: `/file/path/tls.cert`
-- `LND_REST_MACAROON`: `/file/path/admin.macaroon` or Base64/Hex
+For the invoice listener to work you have a publicly accessible URL in your LNbits and must set up [LNPay webhooks](https://dashboard.lnpay.co/webhook/) pointing to `
Audit
+
-
@@ -136,15 +133,7 @@
multiple
:hint="$t('audit_http_methods_hint')"
:label="$t('audit_http_methods_label')"
- :options="[
- 'GET',
- 'POST',
- 'PUT',
- 'PATCH',
- 'DELETE',
- 'HEAD',
- 'OPTIONS'
- ]"
+ :options="['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']"
>
+
+
+
+
+
+ Refresh Interval and History Size are for
+ historical purposes only.
+
+
+
+ API URL and JSON Path fields can use the
+ {to} and {TO} placeholders for the code of the
+ currency
+ {TO} is the uppercase code and {to} is the
+ lowercase code
+
@@ -140,4 +140,4 @@
+
+
+
+
+
+
+ checkout.session.async_payment_failedcheckout.session.async_payment_succeededcheckout.session.completedcheckout.session.expired
+
+
+
+
@@ -12,67 +12,45 @@
- -
-- -
+ {% if LNBITS_NODE_UI_AVAILABLE %} ++
+ {% endif %}
- -
+
-
-
-
- -
+
- -
+
- -
+
- -
+
@@ -151,9 +131,7 @@
- -
+
- -
+
- -
+
-
GET /api/v1/wallet
+ {"X-Api-Key": ""}{"id": <string>, "name": <string>, "balance":
+ <int>}
+ curl api/v1/wallet -H "X-Api-Key:
+ "
+ POST /api/v1/payments
+ {"X-Api-Key": ""}{"out": false, "amount": <int>, "memo": <string>,
+ "expiry": <int>, "unit": <string>, "webhook":
+ <url:string>, "internal": <bool>}
+ {"payment_hash": <string>, "payment_request":
+ <string>}
+ curl -X POST api/v1/payments -d
+ '{"out": false, "amount": <int>, "memo": <string>}' -H
+ "X-Api-Key:
+ " -H
+ "Content-type: application/json"
+ POST /api/v1/payments (reveal
+ admin keys
+ )
+ {"X-Api-Key": ""}
+ {"out": true, "bolt11": <string>}
+ {"payment_hash": <string>}
+ curl -X POST api/v1/payments -d
+ '{"out": true, "bolt11": <string>}' -H "X-Api-Key:
+ " -H "Content-type: application/json"
+ POST
+ /api/v1/payments/decode
+ {"data": <string>}
+ curl -X POST api/v1/payments/decode -d
+ '{"data": <bolt11/lnurl, string>}' -H "Content-type:
+ application/json"
+ GET
+ /api/v1/payments/<payment_hash>
+ {"X-Api-Key": ""}
+ {"paid": <bool>}
+ curl -X GET
+ api/v1/payments/<payment_hash> -H
+ "X-Api-Key:
+ " -H
+ "Content-type: application/json"
+ WS
+ /api/v1/ws/<invoice_key>
+
+ wscat -c /
+ {"balance": <int>, "payment": <object>}
+ Authorization
+
+
+ header.
+ | + Header Name + | ++ Header Value + | +
|---|---|
| + Authorization + | +
+
+
+
+ Bearer
+
+
+
+ |
+
+
+
+
+ +
+
+
+
`name` and
+ `sort description` fields are what the users will
+ see when browsing the list of extensions.
+ `id` field is used internally and in the URL of
+ your extension.
+ created_at, updated_at and
+ extra.
+
+ (Owner Data) that will be used as a title for the public
+ page.
+ (Owner Data) that will be used as a description for the
+ public page. (Client Data) that will be shown as inputs in
+ the public page form.
+ (Client Data) as parameters.
+ (Owner Data) that represents the wallet which
+ will generate the invoice and receive the payments.
+ Wallet will be
+ shown.
+ (Owner Data) that represents the currency
+ which will be used to for the amount.
+ Currency will
+ be shown.
+ (Owner Data) or
+ (Client Data) that represents the amount (in
+ the selected currency).
+ Integer and
+ Float will be shown.
+ (Client Data) that will be set to true when
+ the invoice is paid.
+ Boolean will be
+ shown.
+ + +
+ {{SITE_DESCRIPTION}} +
+ + ++ is requesting an invoice: +
+ {% if LNBITS_DENOMINATION != 'sats' %} ++ Authenticate with ? +
++ For every website and for every LNbits wallet, a new keypair + will be deterministically generated so your identity can't be + tied to your LNbits wallet or linked across websites. No other + data will be shared with + . +
++ Your public key for is: +
+
+
+
+ is requesting
+
+
+
+
+ and a
+ -char
+ comment
+
+
+
+ is requesting
+ between
+ and
+
+
+
+
+ and a
+ -char
+ comment
+
+
+