# RTL: one web interface across LND, Core Lightning and Eclair

> A TypeScript and Angular console that speaks to all three major Lightning node implementations through the same config file, with per-vendor SSO escape hatches and a Docker image, aimed at node operators who move between backends.

**Ride-The-Lightning/RTL** — Ride The Lightning - A full function web browser app for LND, C-Lightning and Eclair

- Repository: https://github.com/Ride-The-Lightning/RTL
- Website: https://www.ridethelightning.info/
- Stars: 801 · Forks: 176
- Language: TypeScript
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/ride-the-lightning-rtl

## One console, three Lightning node implementations

RTL is described as a full function, device agnostic web user interface to help manage Lightning node operations. It is available on LND, Core Lightning and Eclair, and the documentation points at separate setup pages for Core Lightning and Eclair, with LND covered in the main instructions.

That cross-implementation support is the reason the project exists as a distinct product rather than a skin for one node. Lightning nodes differ in their API surface, their authentication artefacts and their terminology, and an operator who runs more than one, or who migrates between them, otherwise has to learn a different console for each. RTL puts the same screens in front of all three.

The audience is a node operator rather than a developer building on Lightning. The prerequisite is stated plainly: a functioning and synced node is required before RTL can run at all. For Raspberry Pi and Linux users, the documentation points at the widely used RaspiBolt guide for setting up a Bitcoin and Lightning node.

RTL is also distributed as part of a set of larger node products, which is the strongest signal about its intended deployment. The README lists RaspiBlitz, Nodl, BTCPayServer, Blockdaemon, myNode, Lux Node, BCubium, Start9Labs, Umbrel and Sovran Systems among the platforms and services where it is available. Those are turnkey node appliances and multi service stacks, and RTL is the interface component they share.

A Docker image is also published, at shahanafarooqui/rtl on Docker Hub, for people running their own node.

## Configuration is one JSON file with per-node blocks

RTL requires its own config file, `RTL-Config.json`, to start the server and to provide user authentication. The documented setup is to rename `Sample-RTL-Config.json` to `RTL-Config.json` in the `./RTL` directory, then locate the macaroon file on the node and the lnd.conf file, and edit the config to match.

The structure is a top level object with the shared settings and a `nodes` array, and each node entry carries an index, a display name, the implementation name, an `authentication` block and a `settings` block. The node entry below is taken from the example configuration, and the authentication block is where the three implementations differ:

```json
  "nodes": [
    {
      "index": 1,
      "lnNode": "LND Testnet",
      "lnImplementation": "LND",
      "authentication": {
        "macaroonPath": "<Complete path of the folder containing LND admin.macaroon for the node>",
        "runePath": "<Complete path including filename for CLN rune for the node, rune format 'LIGHTNING_RUNE="your-rune"'>",
        "lnApiPassword": "<Can be used to provide password in ECL implementation>",
        "swapMacaroonPath": "<Complete path of the folder containing Loop's loop.macaroon for the node>",
        "configPath": "<Optional:Path of the .conf if present locally or empty>",
      },
```

So LND is authenticated by macaroon path, Core Lightning by a rune path in the `LIGHTNING_RUNE="your-rune"` format, and Eclair by an API password. The Loop macaroon path is separate again, because Loop is a swap service rather than the node itself.

The settings block is where node behaviour is configured, with `userPersona` set to OPERATOR, a theme mode and colour, a channel backup path, an optional bitcoind config path, a log level, a fiat conversion toggle, an unannounced channels toggle, and the URLs for the node REST API, the swap server REST API and the block explorer.

Advanced users running several nodes are pointed at a separate multi node setup document, and a full reference of every option lives in the application configurations document.

## Authentication has three modes, and the third one is the vendor's problem

The authentication section is short and worth reading carefully, because the options are not equally safe.

RTL requires the user to be authenticated by the application before it allows access to node functions. A specific password must be provided in `RTL-Config.json`, in plain text, for that authentication, set with `multiPass:<user defined>` in the `Authentication` section of the file. The default initial password is `password`.

That default is the first thing to change. The documentation says so plainly, and it matters because the interface exposes node operations once you are through the login.

For hosted solutions such as BTCPayServer, the authors implemented an SSO setup using a one-time-use cookie, and the config example carries the matching `SSO` block with an `rtlSSO` flag, a cookie path and a logout redirect link. For other vendors with their own authentication service, there is a `disableAuth` option that switches off authentication at the RTL level entirely, with the explicit warning that when using it the security of the deployment is the responsibility of the vendor, and that it is not recommended for standalone users.

That framing is the honest one. A web console that can move channel funds, request swaps and change node settings should not be reachable without authentication, and the SSO path is the right answer for a platform that already has identity. The `disableAuth` path is a legitimate integration point and a real footgun in equal measure.

## Building it from the repository, and what the Docker image does

The installation instructions have two routes, and the documentation marks one of them clearly.

To get a specific version you follow the release page. To download from master, which is explicitly labelled as not recommended, you clone and install:

```bash
git clone https://github.com/Ride-The-Lightning/RTL.git
cd RTL
npm ci --omit=dev --legacy-peer-deps
```

And to update an existing checkout:

```bash
cd RTL
git reset --hard HEAD
git clean -f -d
git pull
npm ci --omit=dev --legacy-peer-deps
```

The `--legacy-peer-deps` flag is needed because the frontend and backend dependency trees do not resolve cleanly under modern peer dependency rules, and `--omit=dev` keeps the runtime install small.

The Dockerfile shows the build shape. The builder stage starts from `node:22-alpine`, copies package.json and package-lock.json first so the dependency layer caches, runs `npm ci --legacy-peer-deps`, copies the source, then runs `npm run buildfrontend` for the Angular application and `npm run buildbackend` for the TypeScript server. It then prunes the non production modules with `npm prune --omit=dev --legacy-peer-deps`.

The runner stage is the same base image with tini installed, copies across `rtl.js`, `package.json`, `frontend`, `backend` and `node_modules`, exposes port 3000 and runs `node rtl` under tini as PID 1, with the `-g` flag so the process group is forwarded.

Two details there are worth noting. The frontend and backend are separate builds, Angular and TypeScript respectively, which is visible in the scripts: `buildfrontend` runs `ng build --configuration production` and `buildbackend` runs `npx tsc --project ./server/tsconfig.server.json`. And the tini entrypoint is what makes container shutdown clean, which for a service holding channel state matters.

## Running it, and the Node version floor

Once the config file is in place, the server starts with one command:

```bash
node rtl
```

and on success the console prints that the server is up and running and to open the UI at http://localhost:3000 or your proxy configured url.

The prerequisites are Node.js v20.19 or above, and the package.json engines field says the same, `>=20.19.0`, with the current package version at 0.15.14-beta. The recommended browsers are Chrome, Firefox and MS Edge, and the frontend is built with Angular, with ngrx store and effects at 21.0.1 and ng-swimlane charts for the visualisation.

For headless machines, the documentation covers configuring RTL as a service, with a systemd unit shown for Raspberry Pi and Linux. The unit declares a dependency on `lnd.service` with `Wants` and `After`, so RTL does not start before the node it manages, and the ExecStart points at the rtl executable.

The backend stack is Express 5 with express-session, cookie-parser, csrf-csrf for CSRF protection, jsonwebtoken, otplib for one time passwords, socket.io-client for live updates, axios for outbound calls, and pdfmake, which tells you RTL can produce a PDF, which is how channel backup exports work.

The test setup is worth one line. The `test` script builds the backend and runs the backend tests with the Node test runner, then runs the Angular tests in ChromeHeadless, and there is a separate `testbackend` script pointing at `test/backend/*.test.mjs`.

## Where RTL is the wrong tool

Three limits are concrete.

The first is that RTL does not replace the node. It is an interface over a node, and it needs a working synced node underneath it. If your problem is that your node is misconfigured, unseeded or out of disk, an interface will not fix that. It also means the operational surface is doubled: you now have node and console to keep alive, and a browser-facing service on port 3000 that a node operator may not otherwise have wanted to expose.

The second is the shared password model. A single `multiPass` string guards the whole interface, and the SSO path depends on a vendor's cookie flow, while `disableAuth` removes authentication entirely. For a small home node run on a LAN that is fine. For anything with more than one person using it, the console has no per user accounts, no roles and no audit trail, and the `userPersona` setting is a single value for the whole deployment rather than a per user role.

The third is the beta naming. The recent releases are all labelled beta, v0.15.14, v0.15.13 and v0.15.12, all tagged in October 2026, October 2026 and September 2026 respectively. That is a fast release cadence on a 0.x version line, which is fine for a tool you run locally and annoying if you want a stable pinned deployment.

The alternative to name is running the node's own interface, LND's own Lightning Terminal or the built in CLN and Eclair interfaces, and using a Lightning node manager for multi node setups. The difference in approach is that those sit closer to the node and expose fewer of its functions through a web server, while RTL gives a single cross implementation surface that also covers Loop swaps, channel backups and a PDF export, at the cost of running another web application in front of your node.

## Conclusion

Adopt RTL if you operate Lightning nodes and need one interface across LND, Core Lightning and Eclair, particularly if you also want Loop swaps and channel operations in the same place. Do not adopt it as a public multi tenant service, because the default authentication is a shared password and the SSO and disableAuth options push the security burden onto whoever fronts it. Verify first which node implementation you run and that the matching macaroon or rune path in RTL-Config.json is correct, that you change the default password before the interface is reachable, and that the Node version is at least 20.19.

## FAQ

### Which Lightning node implementations does RTL support?

LND, Core Lightning and Eclair. The documentation provides separate setup pages for Core Lightning and Eclair, with LND covered in the main instructions, and a multi node setup document for managing several nodes at once.

### How do I install RTL from the repository?

Clone the repository, change into the RTL directory and run `npm ci --omit=dev --legacy-peer-deps`. The documentation recommends downloading a specific version from the release page instead of tracking master.

### How is authentication configured for the RTL console?

A password is set in plain text in RTL-Config.json with `multiPass:<user defined>` in the Authentication section, and the default initial password is `password`. There is also an SSO option using a one-time-use cookie for hosted solutions such as BTCPayServer, and a disableAuth option whose security responsibility passes to the vendor.

### What does the RTL-Config.json file need to contain?

A shared section with multiPass, port, defaultNodeIndex, dbDirectoryPath and an SSO block, plus a nodes array where each entry has an index, a node name, an lnImplementation value, an authentication block with macaroonPath, runePath, lnApiPassword and swapMacaroonPath, and a settings block with log level, URLs and toggles.

### What Node.js version does RTL require?

Node.js v20.19 or above, which matches the engines field in package.json. The recommended browsers are Chrome, Firefox and MS Edge.

## Sources

- [License: MIT](https://github.com/Ride-The-Lightning/RTL/blob/master/LICENSE)
- [Project website](https://www.ridethelightning.info/)
- [README](https://github.com/Ride-The-Lightning/RTL/blob/master/README.md)
- [Releases](https://github.com/Ride-The-Lightning/RTL/releases)
- [Ride-The-Lightning/RTL on GitHub](https://github.com/Ride-The-Lightning/RTL)

---

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