From e5616376005136d69c238993b837535e53bbd8ff Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 1 Oct 2021 11:51:55 +0200 Subject: [PATCH 01/19] minor fixes - bitcoind: Remove obsolete defaultText - clightning: Fix description Option `address` can't be used to specify a socket path because it's used explicitly as an IP address in many places. - lnd: Break up overlong line This is required by commit `services: support 0.0.0.0/:: in `address` options` - nix-bitcoin.nix: Formatting - secrets: Improve descriptions --- modules/bitcoind.nix | 1 - modules/clightning.nix | 2 +- modules/lnd.nix | 4 +++- modules/nix-bitcoin.nix | 2 +- modules/secrets/secrets.nix | 5 +++-- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix index e52b525..07da64d 100644 --- a/modules/bitcoind.nix +++ b/modules/bitcoind.nix @@ -26,7 +26,6 @@ let package = mkOption { type = types.package; default = config.nix-bitcoin.pkgs.bitcoind; - defaultText = "pkgs.blockchains.bitcoind"; description = "The package providing bitcoin binaries."; }; extraConfig = mkOption { diff --git a/modules/clightning.nix b/modules/clightning.nix index 58a59bd..070f73d 100644 --- a/modules/clightning.nix +++ b/modules/clightning.nix @@ -7,7 +7,7 @@ let address = mkOption { type = types.str; default = "127.0.0.1"; - description = "IP address or UNIX domain socket to listen for peer connections."; + description = "Address to listen for peer connections."; }; port = mkOption { type = types.port; diff --git a/modules/lnd.nix b/modules/lnd.nix index 648a2c1..8805622 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -221,7 +221,9 @@ in { in [ (nbLib.script "lnd-create-wallet" '' attempts=250 - while ! { exec 3>/dev/tcp/${cfg.restAddress}/${toString cfg.restPort} && exec 3>&-; } &>/dev/null; do + while ! { + exec 3>/dev/tcp/${cfg.restAddress}/${toString cfg.restPort} && exec 3>&- + } &>/dev/null; do ((attempts-- == 0)) && { echo "lnd REST service unreachable"; exit 1; } sleep 0.1 done diff --git a/modules/nix-bitcoin.nix b/modules/nix-bitcoin.nix index 48cb7c4..bad87c1 100644 --- a/modules/nix-bitcoin.nix +++ b/modules/nix-bitcoin.nix @@ -16,7 +16,7 @@ with lib; torClientAddressWithPort = mkOption { readOnly = true; - default = with config.services.tor.client.socksListenAddress; + default = with config.services.tor.client.socksListenAddress; "${addr}:${toString port}"; }; diff --git a/modules/secrets/secrets.nix b/modules/secrets/secrets.nix index c44ee29..ffd74f8 100644 --- a/modules/secrets/secrets.nix +++ b/modules/secrets/secrets.nix @@ -13,7 +13,8 @@ let type = types.bool; default = false; description = '' - Set permissions for existing secrets in `nix-bitcoin.secretsDir`. + Set permissions for existing secrets in `nix-bitcoin.secretsDir` + before services are started. ''; }; @@ -21,7 +22,7 @@ let type = types.bool; default = false; description = '' - Automatically generate all required secrets at system startup. + Automatically generate all required secrets before services are started. Note: Make sure to create a backup of the generated secrets. ''; }; From 1848c3dd983078e145c2f6a449f61d2e6be55024 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 1 Oct 2021 11:51:56 +0200 Subject: [PATCH 02/19] btcpayserver: minor improvements - Quote datadir - Extract liquidd service variable - Move btcpayserver below liquid in modules list because it depends on liquid --- modules/btcpayserver.nix | 14 +++++++------- modules/modules.nix | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix index aa2422f..786aaf9 100644 --- a/modules/btcpayserver.nix +++ b/modules/btcpayserver.nix @@ -101,7 +101,7 @@ let nbLib = config.nix-bitcoin.lib; nbPkgs = config.nix-bitcoin.pkgs; - bitcoind = config.services.bitcoind; + inherit (config.services) bitcoind liquidd; in { inherit options; @@ -149,9 +149,9 @@ in { port=${toString cfg.nbxplorer.port} ${optionalString cfg.btcpayserver.lbtc '' chains=btc,lbtc - lbtcrpcuser=${cfg.liquidd.rpcuser} - lbtcrpcurl=http://${cfg.liquidd.rpc.address}:${toString cfg.liquidd.rpc.port} - lbtcnodeendpoint=${cfg.liquidd.address}:${toString cfg.liquidd.port} + lbtcrpcuser=${liquidd.rpcuser} + lbtcrpcurl=http://${liquidd.rpc.address}:${toString liquidd.rpc.port} + lbtcnodeendpoint=${liquidd.address}:${toString liquidd.port} ''} ''; in { @@ -221,8 +221,8 @@ in { ''; serviceConfig = nbLib.defaultHardening // { ExecStart = '' - ${cfg.btcpayserver.package}/bin/btcpayserver --conf=${cfg.btcpayserver.dataDir}/settings.config \ - --datadir=${cfg.btcpayserver.dataDir} + ${cfg.btcpayserver.package}/bin/btcpayserver --conf='${cfg.btcpayserver.dataDir}/settings.config' \ + --datadir='${cfg.btcpayserver.dataDir}' ''; User = cfg.btcpayserver.user; Restart = "on-failure"; @@ -236,7 +236,7 @@ in { isSystemUser = true; group = cfg.nbxplorer.group; extraGroups = [ "bitcoinrpc-public" ] - ++ optional cfg.btcpayserver.lbtc cfg.liquidd.group; + ++ optional cfg.btcpayserver.lbtc liquidd.group; home = cfg.nbxplorer.dataDir; }; users.groups.${cfg.nbxplorer.group} = {}; diff --git a/modules/modules.nix b/modules/modules.nix index 0e0ac5a..97c263a 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -18,9 +18,9 @@ ./lightning-loop.nix ./lightning-pool.nix ./charge-lnd.nix - ./btcpayserver.nix ./electrs.nix ./liquid.nix + ./btcpayserver.nix ./joinmarket.nix ./joinmarket-ob-watcher.nix ./hardware-wallets.nix From f61e928139b9b97c4b7afcb773d222691d2df2f6 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 1 Oct 2021 11:51:57 +0200 Subject: [PATCH 03/19] services: support 0.0.0.0/:: in `address` options Previously, client services didn't decode these special INADDR_ANY addresses and failed to connect. --- modules/btcpayserver.nix | 8 ++++---- modules/charge-lnd.nix | 5 +++-- modules/clightning.nix | 2 +- modules/electrs.nix | 2 +- modules/joinmarket.nix | 2 +- modules/lightning-loop.nix | 7 +++---- modules/lightning-pool.nix | 5 ++--- modules/liquid.nix | 2 +- modules/lnd-rest-onion-service.nix | 2 +- modules/lnd.nix | 6 +++--- modules/nodeinfo.nix | 3 ++- modules/onion-services.nix | 2 +- pkgs/lib.nix | 13 +++++++++++++ 13 files changed, 36 insertions(+), 23 deletions(-) diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix index 786aaf9..e44208f 100644 --- a/modules/btcpayserver.nix +++ b/modules/btcpayserver.nix @@ -143,15 +143,15 @@ in { configFile = builtins.toFile "config" '' network=${bitcoind.network} btcrpcuser=${cfg.bitcoind.rpc.users.btcpayserver.name} - btcrpcurl=http://${bitcoind.rpc.address}:${toString cfg.bitcoind.rpc.port} - btcnodeendpoint=${bitcoind.address}:${toString bitcoind.port} + btcrpcurl=http://${nbLib.addressWithPort bitcoind.rpc.address cfg.bitcoind.rpc.port} + btcnodeendpoint=${nbLib.addressWithPort bitcoind.address bitcoind.port} bind=${cfg.nbxplorer.address} port=${toString cfg.nbxplorer.port} ${optionalString cfg.btcpayserver.lbtc '' chains=btc,lbtc lbtcrpcuser=${liquidd.rpcuser} - lbtcrpcurl=http://${liquidd.rpc.address}:${toString liquidd.rpc.port} - lbtcnodeendpoint=${liquidd.address}:${toString liquidd.port} + lbtcrpcurl=http://${nbLib.addressWithPort liquidd.rpc.address liquidd.rpc.port} + lbtcnodeendpoint=${nbLib.addressWithPort liquidd.address liquidd.port} ''} ''; in { diff --git a/modules/charge-lnd.nix b/modules/charge-lnd.nix index f6579c1..6f564dc 100644 --- a/modules/charge-lnd.nix +++ b/modules/charge-lnd.nix @@ -112,9 +112,10 @@ in ExecStart = '' ${config.nix-bitcoin.pkgs.charge-lnd}/bin/charge-lnd \ --lnddir ${dataDir}/lnddir-proxy \ - --grpc ${lnd.rpcAddress}:${toString lnd.rpcPort} \ + --grpc ${nbLib.addressWithPort lnd.rpcAddress lnd.rpcPort} \ --config ${checkedConfig} \ - ${optionalString (electrs != null) "--electrum-server ${electrs.address}:${toString electrs.port}"} \ + ${optionalString (electrs != null) + "--electrum-server ${nbLib.addressWithPort electrs.address electrs.port}"} \ ${escapeShellArgs cfg.extraFlags} ''; Type = "oneshot"; diff --git a/modules/clightning.nix b/modules/clightning.nix index 070f73d..19d8b31 100644 --- a/modules/clightning.nix +++ b/modules/clightning.nix @@ -84,7 +84,7 @@ let ${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"} always-use-proxy=${boolToString cfg.always-use-proxy} bind-addr=${cfg.address}:${toString cfg.port} - bitcoin-rpcconnect=${config.services.bitcoind.rpc.address} + bitcoin-rpcconnect=${nbLib.address config.services.bitcoind.rpc.address} bitcoin-rpcport=${toString config.services.bitcoind.rpc.port} bitcoin-rpcuser=${config.services.bitcoind.rpc.users.public.name} rpc-file-mode=0660 diff --git a/modules/electrs.nix b/modules/electrs.nix index 095f6a0..15cad4c 100644 --- a/modules/electrs.nix +++ b/modules/electrs.nix @@ -96,7 +96,7 @@ in { --daemon-dir='${bitcoind.dataDir}' \ --electrum-rpc-addr=${cfg.address}:${toString cfg.port} \ --monitoring-addr=${cfg.address}:${toString cfg.monitoringPort} \ - --daemon-rpc-addr=${bitcoind.rpc.address}:${toString bitcoind.rpc.port} \ + --daemon-rpc-addr=${nbLib.addressWithPort bitcoind.rpc.address bitcoind.rpc.port} \ ${cfg.extraArgs} ''; User = cfg.user; diff --git a/modules/joinmarket.nix b/modules/joinmarket.nix index f2e92d9..9ac4d8a 100644 --- a/modules/joinmarket.nix +++ b/modules/joinmarket.nix @@ -124,7 +124,7 @@ let [BLOCKCHAIN] blockchain_source = bitcoin-rpc network = ${bitcoind.network} - rpc_host = ${bitcoind.rpc.address} + rpc_host = ${nbLib.address bitcoind.rpc.address} rpc_port = ${toString bitcoind.rpc.port} rpc_user = ${bitcoind.rpc.users.privileged.name} ${optionalString (cfg.rpcWalletFile != null) "rpc_wallet_file = ${cfg.rpcWalletFile}"} diff --git a/modules/lightning-loop.nix b/modules/lightning-loop.nix index b7b388e..1249a3a 100644 --- a/modules/lightning-loop.nix +++ b/modules/lightning-loop.nix @@ -50,7 +50,7 @@ let cli = mkOption { default = pkgs.writeScriptBin "loop" '' ${cfg.package}/bin/loop \ - --rpcserver ${rpclisten} \ + --rpcserver ${nbLib.addressWithPort cfg.rpcAddress cfg.rpcPort} \ --macaroonpath '${cfg.dataDir}/${network}/loop.macaroon' \ --tlscertpath '${secretsDir}/loop-cert' "$@" ''; @@ -66,17 +66,16 @@ let lnd = config.services.lnd; network = config.services.bitcoind.network; - rpclisten = "${cfg.rpcAddress}:${toString cfg.rpcPort}"; configFile = builtins.toFile "loop.conf" '' datadir=${cfg.dataDir} network=${network} - rpclisten=${rpclisten} + rpclisten=${cfg.rpcAddress}:${toString cfg.rpcPort} restlisten=${cfg.restAddress}:${toString cfg.restPort} logdir=${cfg.dataDir}/logs tlscertpath=${secretsDir}/loop-cert tlskeypath=${secretsDir}/loop-key - lnd.host=${lnd.rpcAddress}:${toString lnd.rpcPort} + lnd.host=${nbLib.addressWithPort lnd.rpcAddress lnd.rpcPort} lnd.macaroonpath=${lnd.networkDir}/admin.macaroon lnd.tlspath=${lnd.certPath} diff --git a/modules/lightning-pool.nix b/modules/lightning-pool.nix index 4a9c9ca..0c69d32 100644 --- a/modules/lightning-pool.nix +++ b/modules/lightning-pool.nix @@ -50,7 +50,7 @@ let cli = mkOption { default = pkgs.writeScriptBin "pool" '' exec ${cfg.package}/bin/pool \ - --rpcserver ${rpclisten} \ + --rpcserver ${nbLib.addressWithPort cfg.rpcAddress cfg.rpcPort} \ --network ${network} \ --basedir '${cfg.dataDir}' "$@" ''; @@ -65,9 +65,8 @@ let lnd = config.services.lnd; network = config.services.bitcoind.network; - rpclisten = "${cfg.rpcAddress}:${toString cfg.rpcPort}"; configFile = builtins.toFile "pool.conf" '' - rpclisten=${rpclisten} + rpclisten=${cfg.rpcAddress}:${toString cfg.rpcPort} restlisten=${cfg.restAddress}:${toString cfg.restPort} ${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"} diff --git a/modules/liquid.nix b/modules/liquid.nix index 9a311fc..aaf7059 100644 --- a/modules/liquid.nix +++ b/modules/liquid.nix @@ -169,7 +169,7 @@ let rpcconnect=${cfg.rpc.address} ${lib.concatMapStrings (rpcallowip: "rpcallowip=${rpcallowip}\n") cfg.rpcallowip} rpcuser=${cfg.rpcuser} - mainchainrpchost=${bitcoind.rpc.address} + mainchainrpchost=${nbLib.address bitcoind.rpc.address} mainchainrpcport=${toString bitcoind.rpc.port} mainchainrpcuser=${bitcoind.rpc.users.public.name} diff --git a/modules/lnd-rest-onion-service.nix b/modules/lnd-rest-onion-service.nix index 8b2ea25..3d845c1 100644 --- a/modules/lnd-rest-onion-service.nix +++ b/modules/lnd-rest-onion-service.nix @@ -41,7 +41,7 @@ in { services.tor = { enable = true; relay.onionServices.lnd-rest = nbLib.mkOnionService { - target.addr = lnd.restAddress; + target.addr = nbLib.address lnd.restAddress; target.port = lnd.restPort; port = lnd.restPort; }; diff --git a/modules/lnd.nix b/modules/lnd.nix index 8805622..6da0f18 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -127,7 +127,7 @@ let bitcoind = config.services.bitcoind; - bitcoindRpcAddress = bitcoind.rpc.address; + bitcoindRpcAddress = nbLib.address bitcoind.rpc.address; networkDir = cfg.networkDir; configFile = pkgs.writeText "lnd.conf" '' datadir=${cfg.dataDir} @@ -217,12 +217,12 @@ in { # existing, but the RPC service isn't yet, which results in error # "waiting to start, RPC services not available". curl = "${pkgs.curl}/bin/curl -s --show-error --retry 10 --cacert ${cfg.certPath}"; - restUrl = "https://${cfg.restAddress}:${toString cfg.restPort}/v1"; + restUrl = "https://${nbLib.addressWithPort cfg.restAddress cfg.restPort}/v1"; in [ (nbLib.script "lnd-create-wallet" '' attempts=250 while ! { - exec 3>/dev/tcp/${cfg.restAddress}/${toString cfg.restPort} && exec 3>&- + exec 3>/dev/tcp/${nbLib.address cfg.restAddress}/${toString cfg.restPort} && exec 3>&- } &>/dev/null; do ((attempts-- == 0)) && { echo "lnd REST service unreachable"; exit 1; } sleep 0.1 diff --git a/modules/nodeinfo.nix b/modules/nodeinfo.nix index 5a9599c..8bba8e0 100644 --- a/modules/nodeinfo.nix +++ b/modules/nodeinfo.nix @@ -13,6 +13,7 @@ let }; cfg = config.nix-bitcoin.nodeinfo; + nbLib = config.nix-bitcoin.lib; # Services included in the output services = { @@ -96,7 +97,7 @@ let mkInfo = extraCode: name: cfg: '' add_service("${name}", """ - info["local_address"] = "${cfg.address}:${toString cfg.port}" + info["local_address"] = "${nbLib.addressWithPort cfg.address cfg.port}" '' + mkIfOnionPort name (onionPort: '' set_onion_address(info, "${name}", ${onionPort}) '') + extraCode + '' diff --git a/modules/onion-services.nix b/modules/onion-services.nix index 25c9f45..192ac87 100644 --- a/modules/onion-services.nix +++ b/modules/onion-services.nix @@ -65,7 +65,7 @@ in { in nbLib.mkOnionService { port = if externalPort != null then externalPort else service.port; target.port = service.port; - target.addr = if service.address == "0.0.0.0" then "127.0.0.1" else service.address; + target.addr = nbLib.address service.address; } ); }; diff --git a/pkgs/lib.nix b/pkgs/lib.nix index c7a7480..61db1b0 100644 --- a/pkgs/lib.nix +++ b/pkgs/lib.nix @@ -83,4 +83,17 @@ let self = { map = [ map ]; version = 3; }; + + # Convert a bind address, which may be a special INADDR_ANY address, + # to an actual IP address + address = addr: + if addr == "0.0.0.0" then + "127.0.0.1" + else if addr == "::" then + "::1" + else + addr; + + addressWithPort = addr: port: "${self.address addr}:${toString port}"; + }; in self From 82d910e9371f5fa98f5ba10f1c94ea435700a203 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 1 Oct 2021 11:51:58 +0200 Subject: [PATCH 04/19] nbxplorer: fix bitcoind, liquidd settings - Add nbxplorer to whitelists. This is recommended by the nbxplorer docs and guarantees that nbxplorer can always p2p-connect to bitcoind/liquidd. - Enable bitcoind/liquidd p2p servers via `listen`. --- modules/btcpayserver.nix | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix index e44208f..cc959aa 100644 --- a/modules/btcpayserver.nix +++ b/modules/btcpayserver.nix @@ -106,18 +106,31 @@ in { inherit options; config = mkIf cfg.btcpayserver.enable { - services.bitcoind.enable = true; + services.bitcoind = { + enable = true; + rpc.users.btcpayserver = { + passwordHMACFromFile = true; + rpcwhitelist = cfg.bitcoind.rpc.users.public.rpcwhitelist ++ [ + "setban" + "generatetoaddress" + "getpeerinfo" + ]; + }; + # Enable p2p connections + listen = true; + extraConfig = '' + whitelist=${nbLib.address cfg.nbxplorer.address} + ''; + }; services.clightning.enable = mkIf (cfg.btcpayserver.lightningBackend == "clightning") true; services.lnd.enable = mkIf (cfg.btcpayserver.lightningBackend == "lnd") true; - services.liquidd.enable = mkIf cfg.btcpayserver.lbtc true; - - services.bitcoind.rpc.users.btcpayserver = { - passwordHMACFromFile = true; - rpcwhitelist = cfg.bitcoind.rpc.users.public.rpcwhitelist ++ [ - "setban" - "generatetoaddress" - "getpeerinfo" - ]; + services.liquidd = mkIf cfg.btcpayserver.lbtc { + enable = true; + # Enable p2p connections + listen = true; + extraConfig = '' + whitelist=${nbLib.address cfg.nbxplorer.address} + ''; }; services.lnd.macaroons.btcpayserver = mkIf (cfg.btcpayserver.lightningBackend == "lnd") { From 09169365d8dfb7ed5ec4c2b197b9fd53bff21f19 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 1 Oct 2021 11:51:59 +0200 Subject: [PATCH 05/19] liquid: remove unused features - `hexStr` is unused - Simplify ExecStart options - Quote `dataDir` - Remove unneeded `pidFile` setting --- modules/liquid.nix | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/modules/liquid.nix b/modules/liquid.nix index aaf7059..a0714e9 100644 --- a/modules/liquid.nix +++ b/modules/liquid.nix @@ -143,7 +143,6 @@ let bitcoind = config.services.bitcoind; - pidFile = "${cfg.dataDir}/liquidd.pid"; configFile = pkgs.writeText "elements.conf" '' chain=${bitcoind.makeNetworkName "liquidv1" '' regtest @@ -176,11 +175,6 @@ let # Extra config options (from liquidd nixos service) ${cfg.extraConfig} ''; - cmdlineOptions = concatMapStringsSep " " (arg: "'${arg}'") [ - "-datadir=${cfg.dataDir}" - "-pid=${pidFile}" - ]; - hexStr = types.strMatching "[0-9a-f]+"; rpcUserOpts = { name, ... }: { options = { name = mkOption { @@ -234,8 +228,7 @@ in { Type = "simple"; User = cfg.user; Group = cfg.group; - ExecStart = "${nbPkgs.elementsd}/bin/elementsd ${cmdlineOptions}"; - PIDFile = pidFile; + ExecStart = "${nbPkgs.elementsd}/bin/elementsd -datadir='${cfg.dataDir}'"; Restart = "on-failure"; ReadWritePaths = cfg.dataDir; } // nbLib.allowedIPAddresses cfg.enforceTor; From f36df8f5638ec09cc8ab79a0e20db0fff268175c Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 1 Oct 2021 11:52:00 +0200 Subject: [PATCH 06/19] secure-node: remove redundant bitcoind settings - `discover` is automatically disabled by bitcoind because we're setting `externalip` via the `nix-bitcoin.onionServices` mechanism - `bech32` is bitcoind's default addresstype --- modules/presets/secure-node.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix index fb587fa..0318851 100644 --- a/modules/presets/secure-node.nix +++ b/modules/presets/secure-node.nix @@ -36,8 +36,6 @@ in { enable = true; listen = true; dataDirReadableByGroup = mkIf cfg.electrs.high-memory true; - discover = false; - addresstype = "bech32"; dbCache = 1000; }; From a92d6a8e80ca5cd1a7ee579b9d69ee9dcec8be2e Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 1 Oct 2021 11:52:01 +0200 Subject: [PATCH 07/19] netns: expose bridgeIp as an option Previously, this variable was not accessible to other modules. --- modules/netns-isolation.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix index 88e486d..d0dca07 100644 --- a/modules/netns-isolation.nix +++ b/modules/netns-isolation.nix @@ -47,6 +47,12 @@ let readOnly = true; description = "Exposes netns parameters."; }; + + bridgeIp = mkOption { + default = bridgeIp; + readOnly = true; + description = "IP of the netns bridge interface."; + }; }; cfg = config.nix-bitcoin.netns-isolation; From 1b597f92a64f4a77626d7f77c97260addef6a4ea Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 1 Oct 2021 11:52:02 +0200 Subject: [PATCH 08/19] docs/hardware: add line breaks --- docs/hardware.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/hardware.md b/docs/hardware.md index 46279e8..c5b81dc 100644 --- a/docs/hardware.md +++ b/docs/hardware.md @@ -1,8 +1,14 @@ Hardware requirements --- * Disk space: 500 GB (400GB for Bitcoin blockchain + some room) - * Bitcoin Core pruning is not supported at the moment because it's not supported by c-lightning. It's possible to use pruning but you need to know what you're doing. -* RAM: 2GB of memory. ECC memory is better. Additionally, it's recommended to use DDR4 memory with targeted row refresh (TRR) enabled (https://rambleed.com/). + * Bitcoin Core pruning is not supported at the moment because it's not supported by c-lightning. + It's possible to use pruning but you need to know what you're doing. +* RAM: 2GB of memory. ECC memory is better. Additionally, it's recommended to use DDR4 memory with + targeted row refresh (TRR) enabled (https://rambleed.com/). -Tested hardware includes [pcengine's apu2c4](https://pcengines.ch/apu2c4.htm), [GB-BACE-3150](https://www.gigabyte.com/Mini-PcBarebone/GB-BACE-3150-rev-10), [GB-BACE-3160](https://www.gigabyte.com/de/Mini-PcBarebone/GB-BACE-3160-rev-10#ov). -Some hardware (including Intel NUCs) may not be compatible with the hardened kernel turned on by default (see https://github.com/fort-nix/nix-bitcoin/issues/39#issuecomment-517366093 for a workaround). +Tested hardware includes [pcengine's apu2c4](https://pcengines.ch/apu2c4.htm), +[GB-BACE-3150](https://www.gigabyte.com/Mini-PcBarebone/GB-BACE-3150-rev-10), +[GB-BACE-3160](https://www.gigabyte.com/de/Mini-PcBarebone/GB-BACE-3160-rev-10#ov).\ +Some hardware (including Intel NUCs) may not be compatible with the hardened kernel +turned on by default (see https://github.com/fort-nix/nix-bitcoin/issues/39#issuecomment-517366093 +for a workaround). From e57ab83a5149d97c60a6dc7562ea3bba0ad257d1 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 1 Oct 2021 11:52:03 +0200 Subject: [PATCH 09/19] docs/hardware: update - Update pruning info - Add Raspberry Pi 4 Mentioned here: https://github.com/fort-nix/nix-bitcoin/issues/39#issuecomment-917418830 --- README.md | 2 +- docs/hardware.md | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index e18f8e9..478e6aa 100644 --- a/README.md +++ b/README.md @@ -94,10 +94,10 @@ Note that if the machine you're deploying *from* is insecure, there is nothing n Docs --- -* [FAQ](docs/faq.md) * [Hardware Requirements](docs/hardware.md) * [Install instructions](docs/install.md) * [Usage instructions](docs/usage.md) +* [FAQ](docs/faq.md) Troubleshooting --- diff --git a/docs/hardware.md b/docs/hardware.md index c5b81dc..86a4362 100644 --- a/docs/hardware.md +++ b/docs/hardware.md @@ -1,14 +1,18 @@ Hardware requirements --- -* Disk space: 500 GB (400GB for Bitcoin blockchain + some room) - * Bitcoin Core pruning is not supported at the moment because it's not supported by c-lightning. - It's possible to use pruning but you need to know what you're doing. -* RAM: 2GB of memory. ECC memory is better. Additionally, it's recommended to use DDR4 memory with +* RAM: 2GB. ECC memory is better. Additionally, it's recommended to use DDR4 memory with targeted row refresh (TRR) enabled (https://rambleed.com/). +* Disk space: 500 GB (400GB for Bitcoin blockchain + some room) for an unpruned + instance of Bitcoin Core. + * This can be significantly lowered by enabling pruning. + Note: Pruning is not supported by `electrs`. -Tested hardware includes [pcengine's apu2c4](https://pcengines.ch/apu2c4.htm), -[GB-BACE-3150](https://www.gigabyte.com/Mini-PcBarebone/GB-BACE-3150-rev-10), -[GB-BACE-3160](https://www.gigabyte.com/de/Mini-PcBarebone/GB-BACE-3160-rev-10#ov).\ -Some hardware (including Intel NUCs) may not be compatible with the hardened kernel -turned on by default (see https://github.com/fort-nix/nix-bitcoin/issues/39#issuecomment-517366093 +Tested low-end hardware includes: +- [Raspberry Pi 4](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/) +- [PC Engines apu2c4](https://pcengines.ch/apu2c4.htm) +- [Gigabyte GB-BACE-3150](https://www.gigabyte.com/Mini-PcBarebone/GB-BACE-3150-rev-10) +- [Gigabyte GB-BACE-3160](https://www.gigabyte.com/de/Mini-PcBarebone/GB-BACE-3160-rev-10#ov) + +Some hardware (including Intel NUCs) may not be compatible with the [hardened kernel preset](../modules/presets/hardened.nix) +(See https://github.com/fort-nix/nix-bitcoin/issues/39#issuecomment-517366093 for a workaround). From 2cf12d8765e50e4919b613f5788f91eb938afafd Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 1 Oct 2021 11:52:04 +0200 Subject: [PATCH 10/19] README: minor fixes - `packages and dependencies are pinned` Reworded and moved to `Integrity` - `most packages are built from the NixOS stable channel...` Removed because this is false - `builds happen in a sandboxed environment` Removed because this depends on the user's local nix configuration and cannot be enforced by nix-bitcoin --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 478e6aa..1402e8d 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Features A [configuration preset](modules/presets/secure-node.nix) for setting up a secure node * All applications use Tor for outbound connections and support accepting inbound connections via onion services. -NixOS modules +NixOS modules ([src](modules/modules.nix)) * Application services * [bitcoind](https://github.com/bitcoin/bitcoin), with a default banlist against spy nodes * [clightning](https://github.com/ElementsProject/lightning) with support for announcing an onion service\ @@ -85,10 +85,10 @@ NixOS modules Security --- -* **Simplicity:** Only services you select in `configuration.nix` and their dependencies are installed, packages and dependencies are [pinned](pkgs/nixpkgs-pinned.nix), support for [doas](https://github.com/Duncaen/OpenDoas) ([sudo alternative](https://lobste.rs/s/efsvqu/heap_based_buffer_overflow_sudo_cve_2021#c_c6fcfa)), most packages are built from the [NixOS stable channel](https://github.com/NixOS/nixpkgs/tree/nixos-20.09), with a few exceptions that are built from the nixpkgs unstable channel, builds happen in a [sandboxed environment](https://nixos.org/manual/nix/stable/#conf-sandbox), code is continuously reviewed and refined. -* **Integrity:** Nix package manager, NixOS and packages can be built from source to reduce reliance on binary caches, nix-bitcoin merge commits are signed, all commits are approved by multiple nix-bitcoin developers, upstream packages are cryptographically verified where possible, we use this software ourselves. -* **Principle of Least Privilege:** Services operate with least privileges; they each have their own user and are restricted further with [systemd options](pkgs/lib.nix), [RPC whitelisting](modules/bitcoind-rpc-public-whitelist.nix), and [netns-isolation](modules/netns-isolation.nix). There's a non-root user *operator* to interact with the various services. -* **Defense-in-depth:** nix-bitcoin is built with a [hardened kernel](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/hardened.nix) by default, services are confined through discretionary access control, Linux namespaces, [dbus firewall](modules/security.nix) and seccomp-bpf with continuous improvements. +* **Simplicity:** Only services enabled in `configuration.nix` and their dependencies are installed, support for [doas](https://github.com/Duncaen/OpenDoas) ([sudo alternative](https://lobste.rs/s/efsvqu/heap_based_buffer_overflow_sudo_cve_2021#c_c6fcfa)), code is continuously reviewed and refined. +* **Integrity:** The Nix package manager guarantees that all dependencies are exactly specified, packages can be built from source to reduce reliance on binary caches, nix-bitcoin merge commits are signed, all commits are approved by multiple nix-bitcoin developers, upstream packages are cryptographically verified where possible, we use this software ourselves. +* **Principle of Least Privilege:** Services operate with least privileges; they each have their own user and are restricted further with [systemd features](pkgs/lib.nix), [RPC whitelisting](modules/bitcoind-rpc-public-whitelist.nix) and [netns-isolation](modules/netns-isolation.nix). There's a non-root user *operator* to interact with the various services. +* **Defense-in-depth:** nix-bitcoin supports a [hardened kernel](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/hardened.nix), services are confined through discretionary access control, Linux namespaces, [dbus firewall](modules/security.nix) and seccomp-bpf with continuous improvements. Note that if the machine you're deploying *from* is insecure, there is nothing nix-bitcoin can do to protect itself. From e61c743644a27f47668d477f35903132f17b24bb Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 1 Oct 2021 11:52:05 +0200 Subject: [PATCH 11/19] test: add option `extraTestScript` This allows extending tests.py. --- test/lib/make-test.nix | 1 + test/lib/test-lib.nix | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/test/lib/make-test.nix b/test/lib/make-test.nix index ab1fec3..e7cf84f 100644 --- a/test/lib/make-test.nix +++ b/test/lib/make-test.nix @@ -42,6 +42,7 @@ name: testConfig: builtins.concatStringsSep "\n\n" [ initData (builtins.readFile ./../tests.py) + cfg.test.extraTestScript # Don't run tests in interactive mode. # is_interactive is set in ../run-tests.sh '' diff --git a/test/lib/test-lib.nix b/test/lib/test-lib.nix index f34c5d9..1de2b18 100644 --- a/test/lib/test-lib.nix +++ b/test/lib/test-lib.nix @@ -19,7 +19,11 @@ with lib; dictionary variable 'test_data'. The data is exported via JSON. ''; }; - + extraTestScript = mkOption { + type = types.lines; + default = ""; + description = "Extra lines added to the Python test script."; + }; container = { # Forwarded to extra-container. For descriptions, see # https://github.com/erikarvstedt/extra-container/blob/master/eval-config.nix From 4d5bc810eb7b0af6da5861c22b880d0ad8c2552f Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sat, 2 Oct 2021 11:49:49 +0200 Subject: [PATCH 12/19] secrets: fix setup-secrets in case of no secrets Previously, the glob (*) returned '*' when no files existed in the secrets dir, leading to error `chown: cannot access '*'`. Now `unprocessedFiles` is empty when there are no secrets. Also remove the unneeded sorting of `unprocessedFiles` and remove redundant leading zero in the default mode. --- modules/secrets/secrets.nix | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/secrets/secrets.nix b/modules/secrets/secrets.nix index ffd74f8..4776bca 100644 --- a/modules/secrets/secrets.nix +++ b/modules/secrets/secrets.nix @@ -58,7 +58,7 @@ let }; permissions = mkOption { type = str; - default = "0440"; + default = "440"; }; }; } @@ -205,7 +205,9 @@ in { } # Make all other files accessible to root only - unprocessedFiles=$(comm -23 <(printf '%s\n' *) <(printf '%s\n' "''${processedFiles[@]}" | sort)) + unprocessedFiles=$( + comm -23 <(shopt -s nullglob; printf '%s\n' *) <(printf '%s\n' "''${processedFiles[@]}") + ) if [[ $unprocessedFiles ]]; then IFS=$'\n' chown root: $unprocessedFiles From 3c6a664b7b5e01801ac22f73a02c91985b02e986 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sat, 2 Oct 2021 11:49:50 +0200 Subject: [PATCH 13/19] examples/configuration: show how to enable sudo/doas for `operator` This was brought up by a user on IRC. --- examples/configuration.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/configuration.nix b/examples/configuration.nix index dcf1f06..26f3cfc 100644 --- a/examples/configuration.nix +++ b/examples/configuration.nix @@ -243,6 +243,10 @@ openssh.authorizedKeys.keys = [ "" ]; }; + # FIXME: Uncomment this to allow the operator user to run + # commands as root with `sudo` or `doas` + # users.users.operator.extraGroups = [ "wheel" ]; + # FIXME: add packages you need in your system environment.systemPackages = with pkgs; [ vim @@ -261,5 +265,4 @@ # When upgrading to a backwards-incompatible release, nix-bitcoin will display an # an error and provide hints for migrating your config to the new release. nix-bitcoin.configVersion = "0.0.51"; - } From c8251cdad7d511042c968cd2bda730de2ed5ca2b Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Tue, 5 Oct 2021 15:07:56 +0200 Subject: [PATCH 14/19] onion-services: don't always enable Tor Previously, Tor was always enabled because `cfg` was always nonempty (via definitions at `Set sensible defaults for some services`). Now only enable Tor if there are active onion services. Also rename var `services` -> `onionServices` to improve readability in section `Set getPublicAddressCmd ...` where the same name is also used for option `config.services`. --- modules/onion-services.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/onion-services.nix b/modules/onion-services.nix index 192ac87..490f136 100644 --- a/modules/onion-services.nix +++ b/modules/onion-services.nix @@ -43,18 +43,18 @@ let cfg = config.nix-bitcoin.onionServices; nbLib = config.nix-bitcoin.lib; - services = builtins.attrNames cfg; + onionServices = builtins.attrNames cfg; activeServices = builtins.filter (service: config.services.${service}.enable && cfg.${service}.enable - ) services; + ) onionServices; publicServices = builtins.filter (service: cfg.${service}.public) activeServices; in { inherit options; config = mkMerge [ - (mkIf (cfg != {}) { + (mkIf (activeServices != []) { # Define hidden services services.tor = { enable = true; @@ -93,7 +93,7 @@ in { publicServices' = builtins.filter (service: let srv = cfg.${service}; in srv.public && srv.enable - ) services; + ) onionServices; in genAttrs publicServices' (service: { getPublicAddressCmd = "cat ${config.nix-bitcoin.onionAddresses.dataDir}/services/${service}"; }); From 27905e2c3a64fcf10b41c8c76395b4ce134ec5a3 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Tue, 5 Oct 2021 16:44:00 +0200 Subject: [PATCH 15/19] tests: disable restarting joinmarket-ob-watcher This removes the repeated failure messages from the test log. --- test/tests.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/tests.nix b/test/tests.nix index f68374e..b63973a 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -98,6 +98,10 @@ let txfee = 200; }; + # Disable restarting joinmarket-ob-watcher because it always fails + # on non-synced mainnet nodes + systemd.services.joinmarket-ob-watcher.serviceConfig.Restart = mkForce "no"; + tests.nodeinfo = config.nix-bitcoin.nodeinfo.enable; tests.backups = cfg.backups.enable; From b73c093d3dcb76e91a5ca881ed729cf46643a748 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Wed, 6 Oct 2021 11:27:47 +0200 Subject: [PATCH 16/19] joinmarket-ob-watcher: require nix-bitcoin.service This caused failures in the tests which were ignored because ob-watcher was expected to fail for other reasons. --- modules/joinmarket-ob-watcher.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/joinmarket-ob-watcher.nix b/modules/joinmarket-ob-watcher.nix index b5378b5..faa485c 100644 --- a/modules/joinmarket-ob-watcher.nix +++ b/modules/joinmarket-ob-watcher.nix @@ -93,10 +93,10 @@ in { "d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -" ]; - systemd.services.joinmarket-ob-watcher = { + systemd.services.joinmarket-ob-watcher = rec { wantedBy = [ "multi-user.target" ]; - requires = [ "tor.service" ]; - after = [ "tor.service" ]; + requires = [ "tor.service" "bitcoind.service" ]; + after = requires; # The service writes to HOME/.config/matplotlib environment.HOME = cfg.dataDir; preStart = '' From 0853dedc4321c6d75f6a70c8913952f065f07792 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Tue, 5 Oct 2021 21:44:56 +0200 Subject: [PATCH 17/19] tests/regtest: don't fail when restarting bitcoind --- test/tests.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/tests.nix b/test/tests.nix index b63973a..4e93ae4 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -229,7 +229,8 @@ let services.bitcoind.regtest = true; systemd.services.bitcoind.postStart = mkAfter '' cli=${config.services.bitcoind.cli}/bin/bitcoin-cli - $cli createwallet "test" + # Don't fail when wallet already exists + $cli createwallet "test" || true address=$($cli getnewaddress) $cli generatetoaddress 10 $address ''; From 0c45415c86d6f778f0549c14a1028338917128dc Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Tue, 5 Oct 2021 21:44:57 +0200 Subject: [PATCH 18/19] backups: exclude bitcoind, liquidd txindex data --- modules/backups.nix | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/backups.nix b/modules/backups.nix index 8cda1a6..7731638 100644 --- a/modules/backups.nix +++ b/modules/backups.nix @@ -41,13 +41,19 @@ let cfg = config.services.backups; filelist = pkgs.writeText "filelist.txt" '' - ${optionalString (!cfg.with-bulk-data) "- ${config.services.bitcoind.dataDir}/blocks"} - ${optionalString (!cfg.with-bulk-data) "- ${config.services.bitcoind.dataDir}/chainstate"} + ${optionalString (!cfg.with-bulk-data) '' + - ${config.services.bitcoind.dataDir}/blocks + - ${config.services.bitcoind.dataDir}/chainstate + - ${config.services.bitcoind.dataDir}/indexes + ''} ${config.services.bitcoind.dataDir} ${config.services.clightning.dataDir} ${config.services.lnd.dataDir} - ${optionalString (!cfg.with-bulk-data) "- ${config.services.liquidd.dataDir}/*/blocks"} - ${optionalString (!cfg.with-bulk-data) "- ${config.services.liquidd.dataDir}/*/chainstate"} + ${optionalString (!cfg.with-bulk-data) '' + - ${config.services.liquidd.dataDir}/*/blocks + - ${config.services.liquidd.dataDir}/*/chainstate + - ${config.services.liquidd.dataDir}/*/indexes + ''} ${config.services.liquidd.dataDir} ${optionalString cfg.with-bulk-data "${config.services.electrs.dataDir}"} ${config.services.nbxplorer.dataDir} From 6d694a6269ccc00f50f31788dfd47dff7102e061 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Tue, 5 Oct 2021 21:44:58 +0200 Subject: [PATCH 19/19] backups: allow extraFiles to override default settings By moving them to the top they take precedence over the remaining filelist entries. --- modules/backups.nix | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/backups.nix b/modules/backups.nix index 7731638..8b140cf 100644 --- a/modules/backups.nix +++ b/modules/backups.nix @@ -40,7 +40,12 @@ let cfg = config.services.backups; - filelist = pkgs.writeText "filelist.txt" '' + # Potential backup file paths are are matched against filelist + # entries from top to bottom. + # The first match determines inclusion or exclusion. + filelist = builtins.toFile "filelist.txt" '' + ${builtins.concatStringsSep "\n" cfg.extraFiles} + ${optionalString (!cfg.with-bulk-data) '' - ${config.services.bitcoind.dataDir}/blocks - ${config.services.bitcoind.dataDir}/chainstate @@ -65,9 +70,6 @@ let ${builtins.concatStringsSep "\n" postgresqlBackupPaths} - # Extra files - ${builtins.concatStringsSep "\n" cfg.extraFiles} - # Exclude all unspecified files and directories - / '';