lnd: add neutrino backend support

Add option to use neutrino instead of bitcoind for fetching blockchain
data. This allows running LND as a lightweight client that connects to
remote Bitcoin full nodes via P2P protocol.

New options:
- services.lnd.backend: choose between "bitcoind" (default) or "neutrino"
- services.lnd.neutrino.addpeers: list of Bitcoin node peers to connect to

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
padreug 2025-12-22 09:43:50 +01:00
parent 4f4cb34837
commit b0076a2e1d

View file

@ -144,6 +144,22 @@ let
description = "LND TLS certificate path.";
};
tor = nbLib.tor;
backend = mkOption {
type = types.enum [ "bitcoind" "neutrino" ];
default = "bitcoind";
description = "The backend to use for fetching blockchain data.";
};
neutrino = {
addpeers = mkOption {
type = types.listOf types.str;
default = [];
example = [ "192.168.1.1:8333" "btcd.example.com:8333" ];
description = ''
List of Bitcoin full node peers to connect to via neutrino.addpeer.
Multiple peers provide redundancy for maximum uptime.
'';
};
};
};
cfg = config.services.lnd;
@ -170,15 +186,20 @@ let
restlisten=${cfg.restAddress}:${toString cfg.restPort}
bitcoin.${bitcoind.network}=1
bitcoin.node=bitcoind
${optionalString (cfg.tor.proxy) "tor.active=true"}
${optionalString (cfg.tor-socks != null) "tor.socks=${cfg.tor-socks}"}
bitcoind.rpchost=${bitcoindRpcAddress}:${toString bitcoind.rpc.port}
bitcoind.rpcuser=${bitcoind.rpc.users.public.name}
bitcoind.zmqpubrawblock=${zmqHandleSpecialAddress bitcoind.zmqpubrawblock}
bitcoind.zmqpubrawtx=${zmqHandleSpecialAddress bitcoind.zmqpubrawtx}
${if cfg.backend == "bitcoind" then ''
bitcoin.node=bitcoind
bitcoind.rpchost=${bitcoindRpcAddress}:${toString bitcoind.rpc.port}
bitcoind.rpcuser=${bitcoind.rpc.users.public.name}
bitcoind.zmqpubrawblock=${zmqHandleSpecialAddress bitcoind.zmqpubrawblock}
bitcoind.zmqpubrawtx=${zmqHandleSpecialAddress bitcoind.zmqpubrawtx}
'' else ''
bitcoin.node=neutrino
${lib.concatMapStringsSep "\n" (peer: "neutrino.addpeer=${peer}") cfg.neutrino.addpeers}
''}
wallet-unlock-password-file=${secretsDir}/lnd-wallet-password
@ -202,9 +223,15 @@ in {
services.lnd.port to a port other than 9735.
'';
}
{ assertion = cfg.backend != "neutrino" || cfg.neutrino.addpeers != [];
message = ''
When using neutrino backend, you must configure at least one peer
in services.lnd.neutrino.addpeers.
'';
}
];
services.bitcoind = {
services.bitcoind = mkIf (cfg.backend == "bitcoind") {
enable = true;
# Increase rpc thread count due to reports that lightning implementations fail
@ -225,12 +252,14 @@ in {
systemd.services.lnd = {
wantedBy = [ "multi-user.target" ];
requires = [ "bitcoind.service" ];
after = [ "bitcoind.service" "nix-bitcoin-secrets.target" ];
requires = optional (cfg.backend == "bitcoind") "bitcoind.service";
after = optional (cfg.backend == "bitcoind") "bitcoind.service" ++ [ "nix-bitcoin-secrets.target" ];
preStart = ''
install -m600 ${configFile} '${cfg.dataDir}/lnd.conf'
{
echo "bitcoind.rpcpass=$(cat ${secretsDir}/bitcoin-rpcpassword-public)"
${optionalString (cfg.backend == "bitcoind") ''
echo "bitcoind.rpcpass=$(cat ${secretsDir}/bitcoin-rpcpassword-public)"
''}
${optionalString (cfg.getPublicAddressCmd != "") ''
echo "externalip=$(${cfg.getPublicAddressCmd})"
''}
@ -288,7 +317,7 @@ in {
users.users.${cfg.user} = {
isSystemUser = true;
group = cfg.group;
extraGroups = [ "bitcoinrpc-public" ];
extraGroups = optional (cfg.backend == "bitcoind") "bitcoinrpc-public";
home = cfg.dataDir; # lnd creates .lnd dir in HOME
};
users.groups.${cfg.group} = {};