# LNbits: a wallet server that sits on top of the Lightning node you already run

> LNbits is a MIT licensed Python server that puts a wallet and accounts layer on top of a Lightning funding source, giving you isolated wallets with their own API keys, an HTTP API, and a large extension catalogue. The funding source is an indirection you can change later, the configuration lives partly in the database rather than in the environment, and the default branch is `dev`.

**lnbits/lnbits** — LNbits, free and open-source Lightning wallet and accounts system.

- Repository: https://github.com/lnbits/lnbits
- Website: https://lnbits.com
- Stars: 1,244 · Forks: 431
- Language: Python
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/lnbits-lnbits

## A wallet layer over a funding source you already run

LNbits is described as a lightweight Python server that sits on top of your Lightning funding source, giving you safe, isolated wallets, a clean API, and an extension system for rapidly adding features, without locking you into a single node implementation.

That last clause is the design decision worth understanding. LNbits is not a Lightning node. It does not hold channels, manage liquidity or persist to the chain. It talks to something that does, and that something is the funding source. The README says LNbits runs on top of most Lightning backends, and that you can choose the one you already operate or swap later without changing your app architecture. There is a funding source guide in the documentation for the specifics of each backend.

The lineage is stated too, and it explains a lot. The inspiration for LNbits came from ideas pioneered by OpenNode and LNPay, and both of those today work as funding sources for LNbits. So the ideas that shaped the wallet layer came from two hosted payment providers, and the project is now the piece that lets you keep the same abstraction while owning the backend.

The intended user is broad, and the README's own framing is that you should run it for yourself, for your community, or as part of a larger stack. In practice that means an application developer who needs wallets for their users without operating a Lightning node, a community running workshops, or a small team that wants instant wallets for a proof of concept or user testing.

The project is MIT licensed, the primary language is Python, the homepage is lnbits.com, and the default branch is `dev`. The recent releases are v1.6.2 from 2026-09-18, titled as a PostgreSQL backup hotfix, v1.6.1 from 2026-09-10 and v1.6.0 from 2026-09-02. The last push to `dev` was on 2026-10-19, and the repository is not archived.

## Isolated wallets and the API key that keeps an app off your balance

The first item in the feature list is the one that decides whether you need this at all: harden app security by creating per-wallet API keys so individual apps never touch your full balance.

That is a real architectural idea rather than a slogan. A Lightning node's own API key is all or nothing, so handing it to a third party application, or to a colleague, means handing over the ability to spend everything. LNbits puts a wallet layer in between, and each wallet has its own API keys, so an integration is scoped to the funds in that wallet. The account system section repeats the point, describing the per-wallet API keys as a way to partition the exposure of your funding source.

The account system itself is described in practical terms. LNbits is packaged with tools to help manage funds, such as a table of transactions, a line chart of spending, and export to csv. So the same wallet that receives a payment also carries the history of what was spent from it, and that history can leave the system as a spreadsheet, which is the sort of thing that matters when the wallet holder is a business rather than a person.

The HTTP API is the other half of the contract. The README is blunt about its role, saying that many projects use LNbits to do the heavy lifting for their bitcoin and lightning services. The packaging metadata shows the surface: FastAPI and Starlette with uvicorn, pydantic for validation, `sse-starlette` for server-sent events, `lnurl` for the LNURL protocol, `bolt11` for invoice encoding, `pyln-client` pinned at 25.12.0 for talking to a node, `wallycore` for the cryptographic primitives, and `pyqrcode` for the QR codes a wallet needs.

Two entry points are declared in the packaging, `lnbits` for the server and `lnbits-cli` for a command line interface, which suggests the operations surface goes beyond the web UI.

## Extensions are where the features live, including the ones you write

The extension system is not a plugin layer bolted onto a finished product. It is how the product is assembled.

The README states that all non-core features are installed as extensions, which reduces your code base and makes your LNbits unique to you, and the extension catalogue is browsable at extensions.lnbits.com. The list of what the core keeps for itself is short, and the list of what the extensions cover is long.

The merchant tools are the clearest example of the split. The LNbits stack can process both bitcoin and fiat payments, with orders and inventory shared across extensions and built-in notifications for Nostr, Telegram and email, which the README presents as a turnkey solution for merchants. The dependencies confirm the composition, with `nostr-sdk`, `pywebpush`, `python-multipart` and `embit` present, the last of them annotated as needed for the boltz, lnurldevice and watchonly extensions, and `python-crontab` and `croniter` for the scheduler extension.

There is also a node manager. LNbits comes packaged with a light node management UI to make running your node easier.

The upside of this design is that a small team can ship a feature without touching the core, and a user can compose exactly the tool they need. The downside is that it moves the maintenance burden onto the extension authors, and the extensions are separate projects with their own release cycles. That matters when you are deciding what to depend on.

The README also points to a hardware shop and to a community Telegram channel, and to a demo tip jar hosted on demo.lnbits.com, which gives you a way to see the interface before you install anything.

## Configuration in two places, and the database wins

The `.env.example` file explains its own semantics, and the explanation is the most important operational fact in the repository.

The settings in the file are only set in your `.env` file, and they are not managed by the Admin UI and are not stored in the database. Then there is the Admin Settings block, and the warning attached to `LNBITS_ADMIN_UI=true` is worth reading carefully: enabling this will make LNbits ignore most configurations in the file, and only the configurations defined in `ReadOnlySettings` will still be read from the environment variables. The rest of the settings will be stored in your database and you will be able to change them only through the Admin UI. To reverse it, the file says to disable this and clear the `settings` table from the database to make LNbits use the config file again.

So the configuration surface is a switch. With the admin UI on, the environment file is largely inert and the real configuration lives in the database, editable through the interface. With it off, the file is the source of truth. A deployment that expects configuration management through files and environment variables, and forgets this switch, will find that its settings are being ignored.

The rest of the file is a useful inventory of the operational surface. There is `FIRST_INSTALL_TOKEN`, where if set the user is required to enter this token on the /first_install page. There is `AUTH_HTTPS_ONLY=true`, marked recommended, which when enabled makes auth cookies require HTTPS and SSO reject insecure HTTP. There are the development switches `DEBUG`, `DEBUG_DATABASE`, `BUNDLE_ASSETS` and `PROFILER`, with the note that adding `?profiler=true` to the URL enables the profiler for that request. Logging goes to `LNBITS_DATA_FOLDER/logs/` with `ENABLE_LOG_TO_FILE`, a rotation of 100 MB and a retention of 3 months. `CLEANUP_WALLETS_DAYS=90` is the database cleanup command for wallets. And there are two hard limits, `LNBITS_MAX_USERS` and `LNBITS_MAX_EXTENSIONS`, both commented out with the default of 0 meaning the limit is disabled, which is the setting a shared instance wants and a public one does not.

## Running it: the container, the port and the CLI

The repository ships a Dockerfile, a `docker/` directory, a `Makefile`, an `lnbits.sh` script, and both `poetry.lock` and `uv.lock` alongside `pyproject.toml`, so the project is packaged for several ways of working.

The Dockerfile shows the intended runtime. It is a two stage build on `python:3.12-slim-bookworm`, with the builder installing curl, pkg-config, build-essential, libnss-myhostname and automake, and using uv to sync the project with all extras. The runtime stage additionally installs `postgresql-client-14` and `postgresql-client-common`, and the comment explains why: they are needed for backups, because `pg_dump` is the tool. That detail tells you PostgreSQL backup is a supported path and not an afterthought.

The environment and command are equally explicit:

```bash
ENV LNBITS_PORT="5000"
ENV LNBITS_HOST="0.0.0.0"

EXPOSE 5000

CMD ["sh", "-c", "uv --offline run --no-sync lnbits --port $LNBITS_PORT --host $LNBITS_HOST --forwarded-allow-ips='*'"]
```

Two things in that command deserve attention. The `--forwarded-allow-ips='*'` setting tells the proxy layer to trust forwarded headers from any address, which is what you need behind a reverse proxy but is also a setting you should think about before exposing the port directly. And binding to `0.0.0.0` inside a container is correct, while the `.env.example` default of `HOST=127.0.0.1` is the safer value for a bare metal install.

The Python side has a `requires-python` of `>=3.10,<3.13`, so three Python versions are supported, and the database layer is SQLAlchemy with `aiosqlite` and `asyncpg` for SQLite and PostgreSQL. The web front end is assembled by a set of npm scripts that compile Sass, copy and concatenate vendor assets, and minify the CSS and JavaScript bundles, with a Playwright configuration for end to end tests.

## Where LNbits is the wrong choice

There are three cases where this project is the wrong answer, and the first is the one that matters for money.

The first is custody. LNbits does not hold funds in the sense that a key management system holds them. The funding source holds them, and LNbits talks to the funding source on its behalf. If your requirement is that funds are held under your control with your keys and your infrastructure, LNbits is a layer in front of someone else's balance rather than the thing that keeps the money.

The second is a stable configuration surface. The `LNBITS_ADMIN_UI` behaviour described above means the authoritative configuration can live in the database rather than in files, which is convenient for a hosted instance with an operator UI and awkward for an infrastructure-as-code deployment where a change should be a commit. You can have the file behaviour, but the default in the example file is the opposite.

The third is a feature you can implement more cheaply elsewhere. A wallet system with API keys, a transaction history and a CSV export is not exotic, and if your only need is to receive payments on a single site with a single key, a funding source's own API plus a small service is less to run than a whole server with an extension catalogue.

The alternative approach, and the one to weigh against, is to talk to the funding source directly from your application. The difference in approach is that LNbits gives you wallet isolation, a stable HTTP API, an extension ecosystem and LNURL handling that you would otherwise write, at the cost of a service in your path, a database, and a configuration model that has two modes. For a workshop with a hundred instant wallets, or an application with many users each needing their own key, that trade is usually good. For a single merchant taking payments, the added moving parts may not earn their keep.

Whichever route you take, the pieces the README lists are the ones to check first: the funding source guide tells you whether your node is supported, the install guide in `docs/guide/installation.md` covers the deployment, and the extension catalogue is where the features you will actually want to use are, or are not.

## Conclusion

Adopt LNbits if you want a wallet and accounting layer for your own applications, for a workshop, or for a proof of concept, and you would rather not write wallet management, key management and LNURL handling yourself, since the per-wallet API keys and the extension system cover most of that. Do not adopt it if you need a production custody arrangement, if you cannot accept that the funding source holds the funds, or if you need a stable configuration surface, because the admin UI moves most settings into the database. Verify three things first: that your funding source is one LNbits supports, since the documentation points at a guide covering the backends, that the `LNBITS_ADMIN_UI` setting matches how you intend to manage configuration, because enabling it makes the file settings largely ignored, and that the extension you want is maintained, since all non-core features live there and the repository publishes no release for the extension catalogue.

## FAQ

### What is LNbits and what does it add to a Lightning node?

It is a lightweight Python server that sits on top of your Lightning funding source and gives you safe, isolated wallets, a clean HTTP API and an extension system, without locking you into a single node implementation. The funding source holds the funds and LNbits talks to it.

### How do per-wallet API keys work in LNbits?

Each wallet comes with its own API keys, which is described as a way to partition the exposure of your funding source, so individual apps never touch your full balance. The account system also provides a transaction table, a spending line chart and export to csv.

### Are LNbits features installed as extensions?

All non-core features are installed as extensions, which reduces your code base and lets you extend your install in any direction, and you can create and share your own. The catalogue is browsable at extensions.lnbits.com, and merchant tools such as orders, inventory and notifications for Nostr, Telegram and email are built this way.

### Where does LNbits store its configuration?

In two places, depending on the `LNBITS_ADMIN_UI` setting. The `.env.example` warns that enabling the admin UI makes LNbits ignore most configurations in the file, with only `ReadOnlySettings` still read from environment variables and the rest stored in the database, changeable only through the Admin UI. The file also carries `AUTH_HTTPS_ONLY`, `FIRST_INSTALL_TOKEN` and limits for users and extensions.

### How is the LNbits server started in the Docker image?

The image sets `LNBITS_PORT` to 5000 and `LNBITS_HOST` to 0.0.0.0, exposes port 5000, and runs `uv --offline run --no-sync lnbits --port $LNBITS_PORT --host $LNBITS_HOST --forwarded-allow-ips='*'`. The runtime stage also installs the PostgreSQL client tools because `pg_dump` is used for backups.

## Sources

- [License: MIT](https://github.com/lnbits/lnbits/blob/dev/LICENSE)
- [lnbits/lnbits on GitHub](https://github.com/lnbits/lnbits)
- [Project website](https://lnbits.com)
- [README](https://github.com/lnbits/lnbits/blob/dev/README.md)
- [Releases](https://github.com/lnbits/lnbits/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/lnbits-lnbits
