From cc3d43f4e95b2431eea271f8803d8152f2afc742 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Thu, 28 Oct 2021 22:23:24 +0200 Subject: [PATCH 1/4] bitcoind: set onionPort in bitcoind module This removes the module-level dependency from onion-services to bitcoind. Due to the `or false` fallback, there's no dependency added in the reverse direction. In particular, this allows us to not add a dependency on liquidd in the following commit. --- modules/bitcoind.nix | 4 +++- modules/onion-services.nix | 4 ---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix index 4997024..8a75f2f 100644 --- a/modules/bitcoind.nix +++ b/modules/bitcoind.nix @@ -17,7 +17,9 @@ let }; onionPort = mkOption { type = types.nullOr types.port; - default = null; + # When the bitcoind onion service is enabled, add an onion-tagged socket + # to distinguish local connections from Tor connections + default = if (config.nix-bitcoin.onionServices.bitcoind.enable or false) then 8334 else null; description = '' Port to listen for Tor peer connections. If set, inbound connections to this port are tagged as onion peers. diff --git a/modules/onion-services.nix b/modules/onion-services.nix index 8fa3549..655f579 100644 --- a/modules/onion-services.nix +++ b/modules/onion-services.nix @@ -118,10 +118,6 @@ in { externalPort = 80; }; }; - - # When the bitcoind onion service is enabled, add an onion-tagged socket - # to distinguish local connections from Tor connections - services.bitcoind.onionPort = mkIf (cfg.bitcoind.enable or false) 8334; } ]; } From 8c3a88b2e877df472d69f51a9652a9e1bc3d81dd Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Thu, 28 Oct 2021 22:23:25 +0200 Subject: [PATCH 2/4] update nixpkgs-unstable Switch back from nixpkgs master to unstable. Pkg updates: btcpayserver: 1.2.3 -> 1.2.4 electrs: 0.9.0 -> 0.9.1 elementsd: 0.18.1.12 -> 0.21.0 lightning-pool: 0.5.0-alpha -> 0.5.1-alpha nbxplorer: 2.2.5 -> 2.2.11 - liquidd: add `onionPort` like in bitcoind - tests/electrs: remove KillSignal workaround --- flake.lock | 8 ++++---- flake.nix | 2 +- modules/liquid.nix | 16 ++++++++++++++-- test/tests.nix | 2 -- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 945a198..25f8436 100644 --- a/flake.lock +++ b/flake.lock @@ -33,16 +33,16 @@ }, "nixpkgsUnstable": { "locked": { - "lastModified": 1633514490, - "narHash": "sha256-wQrUBgyF4EXlz9HgEHrQEj9vbgh6+nO8iXc3XCTQkLA=", + "lastModified": 1635295995, + "narHash": "sha256-sGYiXjFlxTTMNb4NSkgvX+knOOTipE6gqwPUQpxNF+c=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1c1b567985bd1be77601657562ed20299d169529", + "rev": "22a500a3f87bbce73bd8d777ef920b43a636f018", "type": "github" }, "original": { "owner": "NixOS", - "ref": "master", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index 65ef974..302b612 100644 --- a/flake.nix +++ b/flake.nix @@ -6,7 +6,7 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.05"; - nixpkgsUnstable.url = "github:NixOS/nixpkgs/master"; + nixpkgsUnstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; flake-utils.url = "github:numtide/flake-utils"; }; diff --git a/modules/liquid.nix b/modules/liquid.nix index a0714e9..86ac93f 100644 --- a/modules/liquid.nix +++ b/modules/liquid.nix @@ -15,6 +15,16 @@ let default = 7042; description = "Override the default port on which to listen for connections."; }; + onionPort = mkOption { + type = types.nullOr types.port; + # When the liquidd onion service is enabled, add an onion-tagged socket + # to distinguish local connections from Tor connections + default = if (config.nix-bitcoin.onionServices.liquidd.enable or false) then 7043 else null; + description = '' + Port to listen for Tor peer connections. + If set, inbound connections to this port are tagged as onion peers. + ''; + }; extraConfig = mkOption { type = types.lines; default = ""; @@ -153,8 +163,10 @@ let ${optionalString (cfg.validatepegin != null) "validatepegin=${if cfg.validatepegin then "1" else "0"}"} # Connection options - ${optionalString cfg.listen "bind=${cfg.address}"} - port=${toString cfg.port} + ${optionalString cfg.listen + "bind=${cfg.address}:${toString cfg.port}"} + ${optionalString (cfg.listen && cfg.onionPort != null) + "bind=${cfg.address}:${toString cfg.onionPort}=onion"} ${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"} listen=${if cfg.listen then "1" else "0"} diff --git a/test/tests.nix b/test/tests.nix index 6e0710f..5ac16fc 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -74,8 +74,6 @@ let tests.charge-lnd = cfg.charge-lnd.enable; tests.electrs = cfg.electrs.enable; - # Sigterm is broken during IBD in version 0.9.0 https://github.com/romanz/electrs/issues/532 - systemd.services.electrs.serviceConfig.KillSignal = "SIGKILL"; tests.liquidd = cfg.liquidd.enable; services.liquidd.extraConfig = mkIf config.test.noConnections "connect=0"; From 1da23cd933aa3b19db7b25599ed4d64a39c4c6cc Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 29 Oct 2021 17:56:57 +0200 Subject: [PATCH 3/4] bitcoind, liquidd: add whitelisted socket This allows whitelisting local services without implicitly whitelisting all inbound onion connections, which would happen when setting bitcoind/liquidd option `whitelist=localhost`. Used by electrs and nbxplorer, which requires the unsafe `mempool` permission. --- modules/bitcoind.nix | 30 ++++++++++++++++++++++++------ modules/btcpayserver.nix | 13 ++++--------- modules/electrs.nix | 6 ++---- modules/liquid.nix | 32 ++++++++++++++++++++++++-------- 4 files changed, 54 insertions(+), 27 deletions(-) diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix index 8a75f2f..c7cd1ae 100644 --- a/modules/bitcoind.nix +++ b/modules/bitcoind.nix @@ -25,6 +25,27 @@ let If set, inbound connections to this port are tagged as onion peers. ''; }; + listen = mkOption { + type = types.bool; + default = false; + description = '' + Listen for peer connections at `address:port` + and `address:onionPort` (if `onionPort` is set). + ''; + }; + listenWhitelisted = mkOption { + type = types.bool; + default = false; + description = '' + Listen for peer connections at `address:whitelistedPort`. + Peers connected through this socket are automatically whitelisted. + ''; + }; + whitelistedPort = mkOption { + type = types.port; + default = 8335; + description = "See `listenWhitelisted`."; + }; getPublicAddressCmd = mkOption { type = types.str; default = ""; @@ -147,11 +168,6 @@ let With `only-outgoing`, incoming i2p connections are disabled. ''; }; - listen = mkOption { - type = types.bool; - default = false; - description = "Accept incoming connections."; - }; dataDirReadableByGroup = mkOption { type = types.bool; default = false; @@ -273,15 +289,17 @@ let ${optionalString (cfg.assumevalid != null) "assumevalid=${cfg.assumevalid}"} # Connection options + listen=${if (cfg.listen || cfg.listenWhitelisted) then "1" else "0"} ${optionalString cfg.listen "bind=${cfg.address}:${toString cfg.port}"} ${optionalString (cfg.listen && cfg.onionPort != null) "bind=${cfg.address}:${toString cfg.onionPort}=onion"} + ${optionalString cfg.listenWhitelisted + "whitebind=${cfg.address}:${toString cfg.whitelistedPort}"} ${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"} ${optionalString (cfg.i2p != false) "i2psam=${nbLib.addressWithPort i2pSAM.address i2pSAM.port}"} ${optionalString (cfg.i2p == "only-outgoing") "i2pacceptincoming=0"} - listen=${if cfg.listen then "1" else "0"} ${optionalString (cfg.discover != null) "discover=${if cfg.discover then "1" else "0"}"} ${lib.concatMapStrings (node: "addnode=${node}\n") cfg.addnodes} diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix index 4a95900..15bbfe8 100644 --- a/modules/btcpayserver.nix +++ b/modules/btcpayserver.nix @@ -116,18 +116,13 @@ in { "getpeerinfo" ]; }; - # Enable p2p connections - listen = true; - extraConfig = '' - whitelist=download@${nbLib.address cfg.nbxplorer.address} - ''; + listenWhitelisted = true; }; services.clightning.enable = mkIf (cfg.btcpayserver.lightningBackend == "clightning") true; services.lnd.enable = mkIf (cfg.btcpayserver.lightningBackend == "lnd") true; services.liquidd = mkIf cfg.btcpayserver.lbtc { enable = true; - # Enable p2p connections - listen = true; + listenWhitelisted = true; }; services.lnd.macaroons.btcpayserver = mkIf (cfg.btcpayserver.lightningBackend == "lnd") { @@ -154,14 +149,14 @@ in { network=${bitcoind.network} btcrpcuser=${cfg.bitcoind.rpc.users.btcpayserver.name} btcrpcurl=http://${nbLib.addressWithPort bitcoind.rpc.address cfg.bitcoind.rpc.port} - btcnodeendpoint=${nbLib.addressWithPort bitcoind.address bitcoind.port} + btcnodeendpoint=${nbLib.addressWithPort bitcoind.address bitcoind.whitelistedPort} bind=${cfg.nbxplorer.address} port=${toString cfg.nbxplorer.port} ${optionalString cfg.btcpayserver.lbtc '' chains=btc,lbtc lbtcrpcuser=${liquidd.rpcuser} lbtcrpcurl=http://${nbLib.addressWithPort liquidd.rpc.address liquidd.rpc.port} - lbtcnodeendpoint=${nbLib.addressWithPort liquidd.address liquidd.port} + lbtcnodeendpoint=${nbLib.addressWithPort liquidd.address bitcoind.whitelistedPort} ''} ''; in { diff --git a/modules/electrs.nix b/modules/electrs.nix index 8072ef9..3dee769 100644 --- a/modules/electrs.nix +++ b/modules/electrs.nix @@ -58,9 +58,7 @@ in { services.bitcoind = { enable = true; - # Enable p2p connections - listen = true; - extraConfig = "whitelist=download@${nbLib.address cfg.address}"; + listenWhitelisted = true; }; systemd.tmpfiles.rules = [ @@ -88,7 +86,7 @@ in { --electrum-rpc-addr=${cfg.address}:${toString cfg.port} \ --monitoring-addr=${cfg.address}:${toString cfg.monitoringPort} \ --daemon-rpc-addr=${nbLib.addressWithPort bitcoind.rpc.address bitcoind.rpc.port} \ - --daemon-p2p-addr=${nbLib.addressWithPort bitcoind.address bitcoind.port} \ + --daemon-p2p-addr=${nbLib.addressWithPort bitcoind.address bitcoind.whitelistedPort} \ ${cfg.extraArgs} ''; User = cfg.user; diff --git a/modules/liquid.nix b/modules/liquid.nix index 86ac93f..36abe7e 100644 --- a/modules/liquid.nix +++ b/modules/liquid.nix @@ -25,6 +25,27 @@ let If set, inbound connections to this port are tagged as onion peers. ''; }; + listen = mkOption { + type = types.bool; + default = false; + description = '' + Listen for peer connections at `address:port` + and `address:onionPort` (if `onionPort` is set). + ''; + }; + listenWhitelisted = mkOption { + type = types.bool; + default = false; + description = '' + Listen for peer connections at `address:whitelistedPort`. + Peers connected through this socket are automatically whitelisted. + ''; + }; + whitelistedPort = mkOption { + type = types.port; + default = 7044; + description = "See `listenWhitelisted`."; + }; extraConfig = mkOption { type = types.lines; default = ""; @@ -80,13 +101,6 @@ let default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null; description = "Connect through SOCKS5 proxy"; }; - listen = mkOption { - type = types.bool; - default = false; - description = '' - If enabled, the liquid service will listen. - ''; - }; dbCache = mkOption { type = types.nullOr (types.ints.between 4 16384); default = null; @@ -163,12 +177,14 @@ let ${optionalString (cfg.validatepegin != null) "validatepegin=${if cfg.validatepegin then "1" else "0"}"} # Connection options + listen=${if (cfg.listen || cfg.listenWhitelisted) then "1" else "0"} ${optionalString cfg.listen "bind=${cfg.address}:${toString cfg.port}"} ${optionalString (cfg.listen && cfg.onionPort != null) "bind=${cfg.address}:${toString cfg.onionPort}=onion"} + ${optionalString cfg.listenWhitelisted + "whitebind=${cfg.address}:${toString cfg.whitelistedPort}"} ${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"} - listen=${if cfg.listen then "1" else "0"} # RPC server options rpcport=${toString cfg.rpc.port} From aada35fc7b5a0a38f56792f8986577a0b19f2e3f Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sat, 30 Oct 2021 14:55:55 +0200 Subject: [PATCH 4/4] minor improvements - README: add matrix room - examples/configuration.nix: explain why bitcoind is enabled by default - btcpayserver: group lnd service settings - clightning: Use public onion port only when the onion service is public This allows users to enable the onion service while announcing a non-onion public address. - netns-isolation: move `readOnly` attr to the top - tests: use mkDefault to allow for easier overriding - tests/btcpayserver: test web server response --- README.md | 5 +++-- examples/configuration.nix | 2 +- modules/btcpayserver.nix | 14 +++++++------- modules/clightning.nix | 6 ++++-- modules/netns-isolation.nix | 4 ++-- test/tests.nix | 4 ++-- test/tests.py | 2 ++ 7 files changed, 21 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 1402e8d..2956de9 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,7 @@ Docs Troubleshooting --- -If you are having problems with nix-bitcoin check the [FAQ](docs/faq.md) or submit an issue. -There's also a `#nix-bitcoin` IRC channel on [libera](https://libera.chat). +If you are having problems with nix-bitcoin check the [FAQ](docs/faq.md) or submit an issue.\ +There's also a Matrix room at [#general:nixbitcoin.org](https://matrix.to/#/#general:nixbitcoin.org) +and a `#nix-bitcoin` IRC channel on [libera](https://libera.chat).\ We are always happy to help. diff --git a/examples/configuration.nix b/examples/configuration.nix index 7f47bc7..dae5a53 100644 --- a/examples/configuration.nix +++ b/examples/configuration.nix @@ -24,7 +24,7 @@ # modules by commenting out their respective line. ### BITCOIND - # Bitcoind is enabled by default. + # Bitcoind is enabled by default via secure-node.nix. # # Set this option to enable pruning with a specified MiB value. # clightning is compatible with pruning. See diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix index 15bbfe8..daa9f16 100644 --- a/modules/btcpayserver.nix +++ b/modules/btcpayserver.nix @@ -119,17 +119,17 @@ in { listenWhitelisted = true; }; services.clightning.enable = mkIf (cfg.btcpayserver.lightningBackend == "clightning") true; - services.lnd.enable = mkIf (cfg.btcpayserver.lightningBackend == "lnd") true; + services.lnd = mkIf (cfg.btcpayserver.lightningBackend == "lnd") { + enable = true; + macaroons.btcpayserver = { + inherit (cfg.btcpayserver) user; + permissions = ''{"entity":"info","action":"read"},{"entity":"onchain","action":"read"},{"entity":"offchain","action":"read"},{"entity":"address","action":"read"},{"entity":"message","action":"read"},{"entity":"peers","action":"read"},{"entity":"signer","action":"read"},{"entity":"invoices","action":"read"},{"entity":"invoices","action":"write"},{"entity":"address","action":"write"}''; + }; + }; services.liquidd = mkIf cfg.btcpayserver.lbtc { enable = true; listenWhitelisted = true; }; - - services.lnd.macaroons.btcpayserver = mkIf (cfg.btcpayserver.lightningBackend == "lnd") { - inherit (cfg.btcpayserver) user; - permissions = ''{"entity":"info","action":"read"},{"entity":"onchain","action":"read"},{"entity":"offchain","action":"read"},{"entity":"address","action":"read"},{"entity":"message","action":"read"},{"entity":"peers","action":"read"},{"entity":"signer","action":"read"},{"entity":"invoices","action":"read"},{"entity":"invoices","action":"write"},{"entity":"address","action":"write"}''; - }; - services.postgresql = { enable = true; ensureDatabases = [ "btcpaydb" ]; diff --git a/modules/clightning.nix b/modules/clightning.nix index 8220ad8..c380e2c 100644 --- a/modules/clightning.nix +++ b/modules/clightning.nix @@ -91,8 +91,10 @@ let ${cfg.extraConfig} ''; - # If the clightning onion service is enabled, use the onion port as the public port - publicPort = if config.nix-bitcoin.onionServices.clightning.enable or false then + # If a public clightning onion service is enabled, use the onion port as the public port + publicPort = if (config.nix-bitcoin.onionServices.clightning.enable or false) + && config.nix-bitcoin.onionServices.clightning.public + then (builtins.elemAt config.services.tor.relay.onionServices.clightning.map 0).port else cfg.port; diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix index 4b612f5..49484e8 100644 --- a/modules/netns-isolation.nix +++ b/modules/netns-isolation.nix @@ -43,14 +43,14 @@ let }; netns = mkOption { - default = netns; readOnly = true; + default = netns; description = "Exposes netns parameters."; }; bridgeIp = mkOption { - default = bridgeIp; readOnly = true; + default = bridgeIp; description = "IP of the netns bridge interface."; }; }; diff --git a/test/tests.nix b/test/tests.nix index 5ac16fc..1e13ad3 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -80,8 +80,8 @@ let tests.btcpayserver = cfg.btcpayserver.enable; services.btcpayserver = { - lightningBackend = "lnd"; - lbtc = true; + lightningBackend = mkDefault "lnd"; + lbtc = mkDefault true; }; # Needed to test macaroon creation environment.systemPackages = mkIfTest "btcpayserver" (with pkgs; [ openssl xxd ]); diff --git a/test/tests.py b/test/tests.py index 163e147..99d0682 100644 --- a/test/tests.py +++ b/test/tests.py @@ -201,6 +201,8 @@ def _(): f"-X GET https://{ip('lnd')}:8080/v1/getinfo | jq", '"version"', ) + # Test web server response + assert_matches(f"curl -L {ip('btcpayserver')}:23000", "Welcome to your BTCPay Server") @test("spark-wallet") def _():