Merge fort-nix/nix-bitcoin#563: lnd: fix missing RPC permissions when bitcoind is pruned

67949a002a lnd: fix missing RPC permissions when bitcoind is pruned (Erik Arvstedt)
49303be2e0 test/shellcheck-services: fix error by excluding unavailable services (Erik Arvstedt)
46f17fe313 test/shellcheck-services: simplify accessing service definitions (Erik Arvstedt)

Pull request description:

ACKs for top commit:
  jonasnick:
    ACK 67949a002a

Tree-SHA512: 28652d8ec67a164aef068f3df32d1ae8df4e0920cafedc6e3d568b631333b29e57f7370e54a82e7cde9710a3df0a1494ed94272af101d31dd7859a08bb363e4b
This commit is contained in:
Jonas Nick 2022-10-28 08:37:57 +00:00
commit 7c16fc5865
No known key found for this signature in database
GPG Key ID: 4861DBF262123605
4 changed files with 51 additions and 52 deletions

View File

@ -174,7 +174,7 @@ let
${optionalString (cfg.tor-socks != null) "tor.socks=${cfg.tor-socks}"} ${optionalString (cfg.tor-socks != null) "tor.socks=${cfg.tor-socks}"}
bitcoind.rpchost=${bitcoindRpcAddress}:${toString bitcoind.rpc.port} bitcoind.rpchost=${bitcoindRpcAddress}:${toString bitcoind.rpc.port}
bitcoind.rpcuser=${bitcoind.rpc.users.public.name} bitcoind.rpcuser=${bitcoind.rpc.users.${rpcUser}.name}
bitcoind.zmqpubrawblock=${bitcoind.zmqpubrawblock} bitcoind.zmqpubrawblock=${bitcoind.zmqpubrawblock}
bitcoind.zmqpubrawtx=${bitcoind.zmqpubrawtx} bitcoind.zmqpubrawtx=${bitcoind.zmqpubrawtx}
@ -182,11 +182,16 @@ let
${cfg.extraConfig} ${cfg.extraConfig}
''; '';
isPruned = bitcoind.prune > 0;
# When bitcoind pruning is enabled, lnd requires non-public RPC commands `getpeerinfo`, `getnodeaddresses`
# to fetch missing blocks from peers (implemented in btcsuite/btcwallet/chain/pruned_block_dispatcher.go)
rpcUser = if isPruned then "lnd" else "public";
in { in {
inherit options; inherit options;
config = mkIf cfg.enable { config = mkIf cfg.enable (mkMerge [ {
assertions = [ assertions = [
{ assertion = { assertion =
!(config.services ? clightning) !(config.services ? clightning)
@ -226,7 +231,7 @@ in {
preStart = '' preStart = ''
install -m600 ${configFile} '${cfg.dataDir}/lnd.conf' install -m600 ${configFile} '${cfg.dataDir}/lnd.conf'
{ {
echo "bitcoind.rpcpass=$(cat ${secretsDir}/bitcoin-rpcpassword-public)" echo "bitcoind.rpcpass=$(cat ${secretsDir}/bitcoin-rpcpassword-${rpcUser})"
${optionalString (cfg.getPublicAddressCmd != "") '' ${optionalString (cfg.getPublicAddressCmd != "") ''
echo "externalip=$(${cfg.getPublicAddressCmd})" echo "externalip=$(${cfg.getPublicAddressCmd})"
''} ''}
@ -304,5 +309,22 @@ in {
makePasswordSecret lnd-wallet-password makePasswordSecret lnd-wallet-password
makeCert lnd '${nbLib.mkCertExtraAltNames cfg.certificate}' makeCert lnd '${nbLib.mkCertExtraAltNames cfg.certificate}'
''; '';
}; }
(mkIf isPruned {
services.bitcoind.rpc.users.lnd = {
passwordHMACFromFile = true;
rpcwhitelist = bitcoind.rpc.users.public.rpcwhitelist ++ [
"getpeerinfo"
"getnodeaddresses"
];
};
nix-bitcoin.secrets = {
bitcoin-rpcpassword-lnd.user = cfg.user;
bitcoin-HMAC-lnd.user = bitcoind.user;
};
nix-bitcoin.generateSecretsCmds.lndBitcoinRPC = ''
makeBitcoinRPCPassword lnd
'';
}) ]);
} }

View File

@ -1,4 +1,4 @@
{ config, pkgs, lib, extendModules, ... }: { config, pkgs, lib, extendModules, ... }@args:
with lib; with lib;
let let
options = { options = {
@ -12,68 +12,38 @@ let
}; };
}; };
# TODO-EXTERNAL:
# This can be removed when https://github.com/NixOS/nixpkgs/pull/189836 is merged.
#
# A list of all systemd service definitions and their locations, with format
# [
# {
# file = ...;
# value = { postgresql = ...; };
# }
# ...
# ]
systemdServiceDefs =
(extendModules {
modules = [
{
# Currently, NixOS modules only allow accessing option definition locations
# via type.merge.
# Override option `systemd.services` and use it to return the list of service defs.
options.systemd.services = lib.mkOption {
type = lib.types.anything // {
merge = loc: defs: defs;
};
};
# Disable all modules that define options.systemd.services so that these
# defs don't collide with our definition
disabledModules = [
"system/boot/systemd.nix"
# These files amend option systemd.services
"testing/service-runner.nix"
"security/systemd-confinement.nix"
];
config._module.check = false;
}
];
}).config.systemd.services;
# A list of all service names that are defined by nix-bitcoin. # A list of all service names that are defined by nix-bitcoin.
# [ "bitcoind", "clightning", ... ] # [ "bitcoind", "clightning", ... ]
# #
# Algorithm: Parse `systemdServiceDefs` and return all services that # Algorithm: Parse defintions of `systemd.services` and return all services
# only have definitions located in the nix-bitcoin source. # that only have definitions located in the nix-bitcoin source.
nix-bitcoin-services = let nix-bitcoin-services = let
systemdServices = args.options.systemd.services;
configSystemdServices = args.config.systemd.services;
nix-bitcoin-source = toString ../..; nix-bitcoin-source = toString ../..;
nbServices = collectServices true; nbServices = collectServices true;
nonNbServices = collectServices false; nonNbServices = collectServices false;
# Return set of services ({ service1 = true; service2 = true; ... }) # Return set of services ({ service1 = true; service2 = true; ... })
# which are either defined or not defined by nix-bitcoin, depending # which are either defined or not defined by nix-bitcoin, depending
# on `fromNixBitcoin`. # on `fromNixBitcoin`.
collectServices = fromNixBitcoin: lib.listToAttrs (builtins.concatLists (map (def: collectServices = fromNixBitcoin: lib.listToAttrs (builtins.concatLists (zipListsWith (services: file:
let let
isNbSource = lib.hasPrefix nix-bitcoin-source def.file; isNbSource = lib.hasPrefix nix-bitcoin-source file;
in in
# Nix has nor boolean XOR, so use `if` # Nix has no boolean XOR, so use `if`
lib.optionals (if fromNixBitcoin then isNbSource else !isNbSource) ( lib.optionals (if fromNixBitcoin then isNbSource else !isNbSource) (
(map (service: { name = service; value = true; }) (builtins.attrNames def.value)) (map (service: { name = service; value = true; }) (builtins.attrNames services))
) )
) systemdServiceDefs)); # TODO-EXTERNAL:
# Use `systemdServices.definitionsWithLocations` when https://github.com/NixOS/nixpkgs/pull/189836
# is included in nixpkgs stable.
) systemdServices.definitions systemdServices.files));
in in
# Set difference: nbServices - nonNbServices # Calculate set difference: nbServices - nonNbServices
builtins.filter (nbService: ! nonNbServices ? ${nbService}) (builtins.attrNames nbServices); # and exclude unavailable services (defined via `mkIf false ...`) by checking `configSystemdServices`.
builtins.filter (nbService:
configSystemdServices ? ${nbService} && (! nonNbServices ? ${nbService})
) (builtins.attrNames nbServices);
# The concatenated list of values of ExecStart, ExecStop, ... (`scriptAttrs`) of all `nix-bitcoin-services`. # The concatenated list of values of ExecStart, ExecStop, ... (`scriptAttrs`) of all `nix-bitcoin-services`.
serviceCmds = let serviceCmds = let

View File

@ -306,6 +306,7 @@ buildable() {
scenario=regtest buildTest "$@" scenario=regtest buildTest "$@"
scenario=hardened buildTest "$@" scenario=hardened buildTest "$@"
scenario=clightningReplication buildTest "$@" scenario=clightningReplication buildTest "$@"
scenario=lndPruned buildTest "$@"
} }
examples() { examples() {

View File

@ -318,6 +318,12 @@ let
services.btcpayserver.lbtc = mkForce false; services.btcpayserver.lbtc = mkForce false;
}; };
# Test the special bitcoin RPC setup that lnd uses when bitcoin is pruned
lndPruned = {
services.lnd.enable = true;
services.bitcoind.prune = 1000;
};
## Examples / debug helper ## Examples / debug helper
# Run a selection of tests in scenario 'netns' # Run a selection of tests in scenario 'netns'