From b0076a2e1da3d8d58427b87d2be0090315925d46 Mon Sep 17 00:00:00 2001 From: padreug Date: Mon, 22 Dec 2025 09:43:50 +0100 Subject: [PATCH] lnd: add neutrino backend support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- modules/lnd.nix | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/modules/lnd.nix b/modules/lnd.nix index 24a5ffe..87497db 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -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} = {};