omnixient/docs/regtest.md
2026-06-28 10:00:14 +02:00

3.9 KiB

Lightning regtest (NixOS-native)

A reproducible, hermetic Lightning regtest stack — bitcoind(regtest) + Core Lightning + LND in one VM — replacing the core of the docker legend-regtest-enviroment (aiolabs/omnixient#27). No docker, no host state; the whole thing is a NixOS VM built from the bitcoin pack's nix-bitcoin modules.

There are two ways to use it, sharing one node definition (tests/regtest-node.nix) so they can't drift:

Mode Command For
CI test nix build .#checks.x86_64-linux.regtest-core -L automated pass/fail (fund → channel → pay → settle)
Interactive dev VM nix run .#regtest poking the nodes by hand in a real shell

Interactive dev VM — nix run .#regtest

The friendly path. Boots the stack headless and drops you straight into an SSH shell as the operator user — real terminal, copy/paste, scrollback, no log spam:

nix run .#regtest

You land in the VM with:

  • user operator, password password (also sudo) — a throwaway local VM with fake coins, so the trivial password is fine. Your settings.sshKeys are accepted too, if set.
  • aliases: btcbitcoin-cli -rpcwallet=test, clnlightning-cli; lncli is the LND CLI as-is. (Plain bitcoin-cli works too — the single test wallet auto-selects.)
  • helper: regtest-fund — funds LND on-chain and opens an LND→CLN channel, so you start with a working channel instead of building it by hand.
  • nodes: bitcoind (regtest), Core Lightning p2p :9735, LND p2p :9736. The chain pre-mines 110 blocks on boot (give it a few seconds).

exit shuts the VM down and discards it (ephemeral disk in a tmp file).

A typical spin

regtest-fund                                   # fund + open a channel

bolt11=$(cln invoice 50000000 demo demo | jq -r .bolt11)
lncli payinvoice --force "$bolt11"             # LND pays CLN
cln listinvoices demo | jq '.invoices[0].status'   # paid

lncli listchannels | jq '.channels[] | {local_balance, remote_balance}'
btc getblockcount

How it boots

nix run .#regtest runs a small wrapper that:

  1. boots packages.regtest-vm (a system.build.vm) headless, with an ephemeral disk and host:2222 → guest:22 forwarded;
  2. waits for SSH, then ssh operator@localhost;
  3. tears the VM down and cleans up the temp disk on exit.

CI test — regtest-core

The automated assertion that the stack actually settles a payment:

nix build .#checks.x86_64-linux.regtest-core -L   # ~60s; exit 0 = passed
nix flake check -L                                 # runs it with the rest

It pre-mines the chain, funds LND, opens an LND→CLN channel, has CLN issue an invoice, LND pays it, and asserts CLN sees it paid. To poke the test node by hand instead, use the raw nixos-test driver:

nix build .#checks.x86_64-linux.regtest-core.driverInteractive
./result/bin/nixos-test-driver      # Python REPL; regtest.succeed("…")

(The nix run .#regtest dev VM is the nicer interactive experience — the driver REPL is awkward for ad-hoc use: Ctrl-C tears down the VM, the QEMU window has no clipboard, and daemon logs flood the console.)

Layout

  • tests/regtest-node.nixshared bitcoind + CLN + LND config (the one source of truth). Consumers also import nix-bitcoin.nixosModules.default.
  • tests/regtest-core.nix — the CI test; imports the shared node.
  • tests/regtest-interactive.nix — the dev-VM layer (SSH, operator login, aliases, regtest-fund, port forward); imports nothing about the test.
  • flake.nix — wires checks.regtest-core, packages.regtest-vm, and apps.regtest.

Follow-up: regtest-full

This is the core tier (#27 tier 1). A regtest-full tier — adding boltz / elements-liquid / litd / lnbits like the docker stack, and more directions (CLN→LND, an eclair node) — is the documented follow-up on aiolabs/omnixient#27.