From 5b7e0d09b2e85386c16d40ad624e824f88f3c015 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:01 +0100
Subject: [PATCH 01/32] bitcoind: add consistent address options
---
modules/bitcoind.nix | 48 ++++++++++++++++-----------------
modules/btcpayserver.nix | 4 +--
modules/clightning.nix | 2 +-
modules/electrs.nix | 2 +-
modules/joinmarket.nix | 2 +-
modules/liquid.nix | 2 +-
modules/lnd.nix | 2 +-
modules/netns-isolation.nix | 4 +--
modules/presets/secure-node.nix | 3 +--
9 files changed, 33 insertions(+), 36 deletions(-)
diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix
index c8650ebb0..f7ba15eef 100644
--- a/modules/bitcoind.nix
+++ b/modules/bitcoind.nix
@@ -22,16 +22,18 @@ let
${optionalString (cfg.assumevalid != null) "assumevalid=${cfg.assumevalid}"}
# Connection options
- ${optionalString cfg.listen "bind=${cfg.bind}"}
- ${optionalString (cfg.port != null) "port=${toString cfg.port}"}
+ ${optionalString cfg.listen "bind=${cfg.address}"}
+ port=${toString cfg.port}
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
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}
# RPC server options
- ${optionalString (cfg.rpcthreads != null) "rpcthreads=${toString cfg.rpcthreads}"}
+ rpcbind=${cfg.rpc.address}
rpcport=${toString cfg.rpc.port}
+ rpcconnect=${cfg.rpc.address}
+ ${optionalString (cfg.rpc.threads != null) "rpcthreads=${toString cfg.rpcthreads}"}
rpcwhitelistdefault=0
${concatMapStrings (user: ''
${optionalString (!user.passwordHMACFromFile) "rpcauth=${user.name}:${passwordHMAC}"}
@@ -39,8 +41,6 @@ let
"rpcwhitelist=${user.name}:${lib.strings.concatStringsSep "," user.rpcwhitelist}"}
'') (builtins.attrValues cfg.rpc.users)
}
- rpcbind=${cfg.rpcbind}
- rpcconnect=${cfg.rpcbind}
${lib.concatMapStrings (rpcallowip: "rpcallowip=${rpcallowip}\n") cfg.rpcallowip}
# Wallet options
@@ -57,6 +57,16 @@ in {
options = {
services.bitcoind = {
enable = mkEnableOption "Bitcoin daemon";
+ address = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = "Address to listen for peer connections.";
+ };
+ port = mkOption {
+ type = types.port;
+ default = 8333;
+ description = "Port to listen for peer connections.";
+ };
package = mkOption {
type = types.package;
default = config.nix-bitcoin.pkgs.bitcoind;
@@ -77,13 +87,6 @@ in {
default = "/var/lib/bitcoind";
description = "The data directory for bitcoind.";
};
- bind = mkOption {
- type = types.str;
- default = "127.0.0.1";
- description = ''
- Bind to given address and always listen on it.
- '';
- };
user = mkOption {
type = types.str;
default = "bitcoin";
@@ -95,10 +98,17 @@ in {
description = "The group as which to run bitcoind.";
};
rpc = {
+ address = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = ''
+ Address to listen for JSON-RPC connections.
+ '';
+ };
port = mkOption {
type = types.port;
default = 8332;
- description = "Port on which to listen for JSON-RPC connections.";
+ description = "Port to listen for JSON-RPC connections.";
};
users = mkOption {
default = {};
@@ -149,13 +159,6 @@ in {
default = null;
description = "Set the number of threads to service RPC calls";
};
- rpcbind = mkOption {
- type = types.str;
- default = "127.0.0.1";
- description = ''
- Bind to given address to listen for JSON-RPC connections.
- '';
- };
rpcallowip = mkOption {
type = types.listOf types.str;
default = [ "127.0.0.1" ];
@@ -176,11 +179,6 @@ in {
readOnly = true;
default = mainnet: regtest: if cfg.regtest then regtest else mainnet;
};
- port = mkOption {
- type = types.nullOr types.port;
- default = null;
- description = "Override the default port on which to listen for connections.";
- };
proxy = mkOption {
type = types.nullOr types.str;
default = if cfg.enforceTor then config.services.tor.client.socksListenAddress else null;
diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix
index 427a08a58..77566059c 100644
--- a/modules/btcpayserver.nix
+++ b/modules/btcpayserver.nix
@@ -117,8 +117,8 @@ in {
configFile = builtins.toFile "config" ''
network=${config.services.bitcoind.network}
btcrpcuser=${cfg.bitcoind.rpc.users.btcpayserver.name}
- btcrpcurl=http://${config.services.bitcoind.rpcbind}:${toString cfg.bitcoind.rpc.port}
- btcnodeendpoint=${config.services.bitcoind.bind}:8333
+ btcrpcurl=http://${config.services.bitcoind.rpc.address}:${toString cfg.bitcoind.rpc.port}
+ btcnodeendpoint=${config.services.bitcoind.address}:${toString config.services.bitcoind.port}
bind=${cfg.nbxplorer.bind}
port=${toString cfg.nbxplorer.port}
'';
diff --git a/modules/clightning.nix b/modules/clightning.nix
index 38f3b9dc4..b5b030bb2 100644
--- a/modules/clightning.nix
+++ b/modules/clightning.nix
@@ -14,7 +14,7 @@ let
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
always-use-proxy=${if cfg.always-use-proxy then "true" else "false"}
bind-addr=${cfg.bind-addr}:${toString cfg.bindport}
- bitcoin-rpcconnect=${config.services.bitcoind.rpcbind}
+ bitcoin-rpcconnect=${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 5258317cf..b503908ef 100644
--- a/modules/electrs.nix
+++ b/modules/electrs.nix
@@ -95,7 +95,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.rpcbind}:${toString bitcoind.rpc.port} \
+ --daemon-rpc-addr=${bitcoind.rpc.address}:${toString bitcoind.rpc.port} \
${cfg.extraArgs}
'';
User = cfg.user;
diff --git a/modules/joinmarket.nix b/modules/joinmarket.nix
index 1e1ad8bd8..816041f2a 100644
--- a/modules/joinmarket.nix
+++ b/modules/joinmarket.nix
@@ -21,7 +21,7 @@ let
[BLOCKCHAIN]
blockchain_source = bitcoin-rpc
network = ${bitcoind.network}
- rpc_host = ${bitcoind.rpcbind}
+ rpc_host = ${bitcoind.rpc.address}
rpc_port = ${toString bitcoind.rpc.port}
rpc_user = ${bitcoind.rpc.users.privileged.name}
@@RPC_PASSWORD@@
diff --git a/modules/liquid.nix b/modules/liquid.nix
index ec3ee6e4d..954b00601 100644
--- a/modules/liquid.nix
+++ b/modules/liquid.nix
@@ -32,7 +32,7 @@ let
${lib.concatMapStrings (rpcallowip: "rpcallowip=${rpcallowip}\n") cfg.rpcallowip}
${optionalString (cfg.rpcuser != null) "rpcuser=${cfg.rpcuser}"}
${optionalString (cfg.rpcpassword != null) "rpcpassword=${cfg.rpcpassword}"}
- mainchainrpchost=${config.services.bitcoind.rpcbind}
+ mainchainrpchost=${config.services.bitcoind.rpc.address}
mainchainrpcport=${toString config.services.bitcoind.rpc.port}
mainchainrpcuser=${config.services.bitcoind.rpc.users.public.name}
diff --git a/modules/lnd.nix b/modules/lnd.nix
index 7df793493..f6225d2ca 100644
--- a/modules/lnd.nix
+++ b/modules/lnd.nix
@@ -8,7 +8,7 @@ let
secretsDir = config.nix-bitcoin.secretsDir;
bitcoind = config.services.bitcoind;
- bitcoindRpcAddress = bitcoind.rpcbind;
+ bitcoindRpcAddress = bitcoind.rpc.address;
onion-chef-service = (if cfg.announce-tor then [ "onion-chef.service" ] else []);
networkDir = "${cfg.dataDir}/chain/bitcoin/${bitcoind.network}";
configFile = pkgs.writeText "lnd.conf" ''
diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix
index 0d335f58a..cb61410ed 100644
--- a/modules/netns-isolation.nix
+++ b/modules/netns-isolation.nix
@@ -245,8 +245,8 @@ in {
};
services.bitcoind = {
- bind = netns.bitcoind.address;
- rpcbind = netns.bitcoind.address;
+ address = netns.bitcoind.address;
+ rpc.address = netns.bitcoind.address;
rpcallowip = [
bridgeIp # For operator user
netns.bitcoind.address
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index c4f06fa0d..3d40bb7e3 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -53,7 +53,6 @@ in {
listen = true;
dataDirReadableByGroup = mkIf cfg.electrs.high-memory true;
enforceTor = true;
- port = 8333;
assumevalid = "00000000000000000000e5abc3a74fe27dc0ead9c70ea1deb456f11c15fd7bc6";
addnodes = [ "ecoc5q34tmbq54wl.onion" ];
discover = false;
@@ -63,7 +62,7 @@ in {
# under high bitcoind rpc load
rpcthreads = 16;
};
- services.tor.hiddenServices.bitcoind = mkHiddenService { port = cfg.bitcoind.port; toHost = cfg.bitcoind.bind; };
+ services.tor.hiddenServices.bitcoind = mkHiddenService { port = cfg.bitcoind.port; toHost = cfg.bitcoind.address; };
# clightning
services.clightning.enforceTor = true;
From dd4a0238f9bcc4148eb718933d5ab95ca211e4b9 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:02 +0100
Subject: [PATCH 02/32] bitcoind: group rpc options under parent option 'rpc'
---
modules/bitcoind.nix | 28 ++++++++++++++--------------
modules/netns-isolation.nix | 2 +-
modules/presets/secure-node.nix | 2 +-
3 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix
index f7ba15eef..92f3516dc 100644
--- a/modules/bitcoind.nix
+++ b/modules/bitcoind.nix
@@ -33,7 +33,7 @@ let
rpcbind=${cfg.rpc.address}
rpcport=${toString cfg.rpc.port}
rpcconnect=${cfg.rpc.address}
- ${optionalString (cfg.rpc.threads != null) "rpcthreads=${toString cfg.rpcthreads}"}
+ ${optionalString (cfg.rpc.threads != null) "rpcthreads=${toString cfg.rpc.threads}"}
rpcwhitelistdefault=0
${concatMapStrings (user: ''
${optionalString (!user.passwordHMACFromFile) "rpcauth=${user.name}:${passwordHMAC}"}
@@ -41,7 +41,7 @@ let
"rpcwhitelist=${user.name}:${lib.strings.concatStringsSep "," user.rpcwhitelist}"}
'') (builtins.attrValues cfg.rpc.users)
}
- ${lib.concatMapStrings (rpcallowip: "rpcallowip=${rpcallowip}\n") cfg.rpcallowip}
+ ${lib.concatMapStrings (rpcallowip: "rpcallowip=${rpcallowip}\n") cfg.rpc.allowip}
# Wallet options
${optionalString (cfg.addresstype != null) "addresstype=${cfg.addresstype}"}
@@ -110,6 +110,18 @@ in {
default = 8332;
description = "Port to listen for JSON-RPC connections.";
};
+ threads = mkOption {
+ type = types.nullOr types.ints.u16;
+ default = null;
+ description = "The number of threads to service RPC calls.";
+ };
+ allowip = mkOption {
+ type = types.listOf types.str;
+ default = [ "127.0.0.1" ];
+ description = ''
+ Allow JSON-RPC connections from specified sources.
+ '';
+ };
users = mkOption {
default = {};
example = {
@@ -154,18 +166,6 @@ in {
'';
};
};
- rpcthreads = mkOption {
- type = types.nullOr types.ints.u16;
- default = null;
- description = "Set the number of threads to service RPC calls";
- };
- rpcallowip = mkOption {
- type = types.listOf types.str;
- default = [ "127.0.0.1" ];
- description = ''
- Allow JSON-RPC connections from specified source.
- '';
- };
regtest = mkOption {
type = types.bool;
default = false;
diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix
index cb61410ed..835ce4d17 100644
--- a/modules/netns-isolation.nix
+++ b/modules/netns-isolation.nix
@@ -247,7 +247,7 @@ in {
services.bitcoind = {
address = netns.bitcoind.address;
rpc.address = netns.bitcoind.address;
- rpcallowip = [
+ rpc.allowip = [
bridgeIp # For operator user
netns.bitcoind.address
] ++ map (n: netns.${n}.address) netns.bitcoind.availableNetns;
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 3d40bb7e3..a5a0acd0c 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -60,7 +60,7 @@ in {
dbCache = 1000;
# higher rpcthread count due to reports that lightning implementations fail
# under high bitcoind rpc load
- rpcthreads = 16;
+ rpc.threads = 16;
};
services.tor.hiddenServices.bitcoind = mkHiddenService { port = cfg.bitcoind.port; toHost = cfg.bitcoind.address; };
From b41a720c28a426b1576a063ab74e295b70a5b13e Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:03 +0100
Subject: [PATCH 03/32] lnd: add consistent address options
Also fix btcpayserver by connecting to the lnd restAddress instead of the p2p address.
---
examples/configuration.nix | 2 +-
modules/btcpayserver.nix | 2 +-
modules/lightning-loop.nix | 2 +-
modules/lnd.nix | 46 ++++++++++++++++-----------------
modules/modules.nix | 4 +--
modules/netns-isolation.nix | 6 ++---
modules/presets/secure-node.nix | 2 +-
test/tests.nix | 2 +-
8 files changed, 32 insertions(+), 34 deletions(-)
diff --git a/examples/configuration.nix b/examples/configuration.nix
index 9545d0fe2..4d56fe211 100644
--- a/examples/configuration.nix
+++ b/examples/configuration.nix
@@ -50,7 +50,7 @@
# Uncomment the following line in order to enable lnd, a lightning
# implementation written in Go. In order to avoid collisions with clightning
# you must disable clightning or change the services.clightning.bindport or
- # services.lnd.listenPort to a port other than 9735.
+ # services.lnd.port to a port other than 9735.
# services.lnd.enable = true;
# Enable this option to announce our Tor Hidden Service. By default lnd
# offers outgoing functionality, but doesn't announce the Tor Hidden Service
diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix
index 77566059c..949cbce75 100644
--- a/modules/btcpayserver.nix
+++ b/modules/btcpayserver.nix
@@ -163,7 +163,7 @@ in {
'');
lndConfig =
"btclightning=type=lnd-rest;" +
- "server=https://${toString cfg.lnd.listen}:${toString cfg.lnd.restPort}/;" +
+ "server=https://${cfg.lnd.restAddress}:${toString cfg.lnd.restPort}/;" +
"macaroonfilepath=/run/lnd/btcpayserver.macaroon;" +
"certthumbprint=";
in let self = {
diff --git a/modules/lightning-loop.nix b/modules/lightning-loop.nix
index 870229758..37d944860 100644
--- a/modules/lightning-loop.nix
+++ b/modules/lightning-loop.nix
@@ -17,7 +17,7 @@ let
tlscertpath=${secretsDir}/loop-cert
tlskeypath=${secretsDir}/loop-key
- lnd.host=${config.services.lnd.rpclisten}:${toString config.services.lnd.rpcPort}
+ lnd.host=${config.services.lnd.rpcAddress}:${toString config.services.lnd.rpcPort}
lnd.macaroondir=${config.services.lnd.networkDir}
lnd.tlspath=${secretsDir}/lnd-cert
diff --git a/modules/lnd.nix b/modules/lnd.nix
index f6225d2ca..226b60c7d 100644
--- a/modules/lnd.nix
+++ b/modules/lnd.nix
@@ -17,9 +17,9 @@ let
tlscertpath=${secretsDir}/lnd-cert
tlskeypath=${secretsDir}/lnd-key
- listen=${toString cfg.listen}:${toString cfg.listenPort}
- rpclisten=${cfg.rpclisten}:${toString cfg.rpcPort}
- restlisten=${cfg.restlisten}:${toString cfg.restPort}
+ listen=${toString cfg.address}:${toString cfg.port}
+ rpclisten=${cfg.rpcAddress}:${toString cfg.rpcPort}
+ restlisten=${cfg.restAddress}:${toString cfg.restPort}
bitcoin.${bitcoind.network}=1
bitcoin.active=1
@@ -55,39 +55,37 @@ in {
default = networkDir;
description = "The network data directory.";
};
- listen = mkOption {
- type = config.nix-bitcoin.pkgs.lib.ipv4Address;
+ address = mkOption {
+ type = types.str;
default = "localhost";
- description = "Bind to given address to listen to peer connections";
+ description = "Address to listen for peer connections";
};
- listenPort = mkOption {
+ port = mkOption {
type = types.port;
default = 9735;
- description = "Bind to given port to listen to peer connections";
+ description = "Port to listen for peer connections";
};
- rpclisten = mkOption {
+ rpcAddress = mkOption {
type = types.str;
default = "localhost";
- description = ''
- Bind to given address to listen to RPC connections.
- '';
+ description = "Address to listen for RPC connections.";
};
- restlisten = mkOption {
+ rpcPort = mkOption {
+ type = types.port;
+ default = 10009;
+ description = "Port to listen for gRPC connections.";
+ };
+ restAddress = mkOption {
type = types.str;
default = "localhost";
description = ''
- Bind to given address to listen to REST connections.
+ Address to listen for REST connections.
'';
};
- rpcPort = mkOption {
- type = types.port;
- default = 10009;
- description = "Port on which to listen for gRPC connections.";
- };
restPort = mkOption {
type = types.port;
default = 8080;
- description = "Port on which to listen for REST connections.";
+ description = "Port to listen for REST connections.";
};
tor-socks = mkOption {
type = types.nullOr types.str;
@@ -138,7 +136,7 @@ in {
# Switch user because lnd makes datadir contents readable by user only
''
sudo -u lnd ${cfg.package}/bin/lncli \
- --rpcserver ${cfg.rpclisten}:${toString cfg.rpcPort} \
+ --rpcserver ${cfg.rpcAddress}:${toString cfg.rpcPort} \
--tlscertpath '${secretsDir}/lnd-cert' \
--macaroonpath '${networkDir}/admin.macaroon' "$@"
'';
@@ -187,12 +185,12 @@ in {
RestartSec = "10s";
ReadWritePaths = "${cfg.dataDir}";
ExecStartPost = let
- restUrl = "https://${cfg.restlisten}:${toString cfg.restPort}/v1";
+ restUrl = "https://${cfg.restAddress}:${toString cfg.restPort}/v1";
in [
# Run fully privileged for secrets dir write access
"+${nix-bitcoin-services.script ''
attempts=250
- while ! { exec 3>/dev/tcp/${cfg.restlisten}/${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
@@ -234,7 +232,7 @@ in {
fi
# Wait until the RPC port is open
- while ! { exec 3>/dev/tcp/${cfg.rpclisten}/${toString cfg.rpcPort}; } &>/dev/null; do
+ while ! { exec 3>/dev/tcp/${cfg.rpcAddress}/${toString cfg.rpcPort}; } &>/dev/null; do
sleep 0.1
done
diff --git a/modules/modules.nix b/modules/modules.nix
index 96fc869bc..fb366dd1d 100644
--- a/modules/modules.nix
+++ b/modules/modules.nix
@@ -58,11 +58,11 @@ with lib;
config = {
assertions = [
- { assertion = (config.services.lnd.enable -> ( !config.services.clightning.enable || config.services.clightning.bindport != config.services.lnd.listenPort));
+ { assertion = (config.services.lnd.enable -> ( !config.services.clightning.enable || config.services.clightning.bindport != config.services.lnd.port));
message = ''
LND and clightning can't both bind to lightning port 9735. Either
disable LND/clightning or change services.clightning.bindPort or
- services.lnd.listenPort to a port other than 9735.
+ services.lnd.port to a port other than 9735.
'';
}
];
diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix
index 835ce4d17..47bf3f113 100644
--- a/modules/netns-isolation.nix
+++ b/modules/netns-isolation.nix
@@ -257,9 +257,9 @@ in {
services.clightning.bind-addr = netns.clightning.address;
services.lnd = {
- listen = netns.lnd.address;
- rpclisten = netns.lnd.address;
- restlisten = netns.lnd.address;
+ address = netns.lnd.address;
+ rpcAddress = netns.lnd.address;
+ restAddress = netns.lnd.address;
};
services.liquidd = {
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index a5a0acd0c..87b59be8e 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -74,7 +74,7 @@ in {
# lnd
services.lnd.enforceTor = true;
- services.tor.hiddenServices.lnd = mkIf cfg.lnd.enable (mkHiddenService { port = cfg.lnd.onionport; toHost = cfg.lnd.listen; toPort = cfg.lnd.listenPort; });
+ services.tor.hiddenServices.lnd = mkIf cfg.lnd.enable (mkHiddenService { port = cfg.lnd.onionport; toHost = cfg.lnd.address; toPort = cfg.lnd.port; });
# lightning-loop
services.lightning-loop.enforceTor = true;
diff --git a/test/tests.nix b/test/tests.nix
index 10c608dea..758e9b657 100644
--- a/test/tests.nix
+++ b/test/tests.nix
@@ -44,7 +44,7 @@ let testEnv = rec {
tests.spark-wallet = cfg.spark-wallet.enable;
tests.lnd = cfg.lnd.enable;
- services.lnd.listenPort = 9736;
+ services.lnd.port = 9736;
tests.lightning-loop = cfg.lightning-loop.enable;
From e78a6096871ad88421f7673f24139d0c3f51d867 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:04 +0100
Subject: [PATCH 04/32] clightning: add consistent address options
Also remove option 'autolisten'. This option has no effect because
option 'bind-addr' is always set.
---
examples/configuration.nix | 2 +-
modules/clightning.nix | 28 ++++++++++------------------
modules/modules.nix | 2 +-
modules/netns-isolation.nix | 2 +-
modules/presets/secure-node.nix | 4 ++--
5 files changed, 15 insertions(+), 23 deletions(-)
diff --git a/examples/configuration.nix b/examples/configuration.nix
index 4d56fe211..c16e31e41 100644
--- a/examples/configuration.nix
+++ b/examples/configuration.nix
@@ -49,7 +49,7 @@
### LND
# Uncomment the following line in order to enable lnd, a lightning
# implementation written in Go. In order to avoid collisions with clightning
- # you must disable clightning or change the services.clightning.bindport or
+ # you must disable clightning or change the services.clightning.port or
# services.lnd.port to a port other than 9735.
# services.lnd.enable = true;
# Enable this option to announce our Tor Hidden Service. By default lnd
diff --git a/modules/clightning.nix b/modules/clightning.nix
index b5b030bb2..23f2307f5 100644
--- a/modules/clightning.nix
+++ b/modules/clightning.nix
@@ -13,7 +13,7 @@ let
bitcoin-datadir=${config.services.bitcoind.dataDir}
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
always-use-proxy=${if cfg.always-use-proxy then "true" else "false"}
- bind-addr=${cfg.bind-addr}:${toString cfg.bindport}
+ bind-addr=${cfg.address}:${toString cfg.port}
bitcoin-rpcconnect=${config.services.bitcoind.rpc.address}
bitcoin-rpcport=${toString config.services.bitcoind.rpc.port}
bitcoin-rpcuser=${config.services.bitcoind.rpc.users.public.name}
@@ -29,13 +29,15 @@ in {
If enabled, the clightning service will be installed.
'';
};
- autolisten = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Bind (and maybe announce) on IPv4 and IPv6 interfaces if no addr,
- bind-addr or announce-addr options are specified.
- '';
+ address = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = "IP address or UNIX domain socket to listen for peer connections.";
+ };
+ port = mkOption {
+ type = types.port;
+ default = 9735;
+ description = "Port to listen for peer connections.";
};
proxy = mkOption {
type = types.nullOr types.str;
@@ -49,16 +51,6 @@ in {
Always use the *proxy*, even to connect to normal IP addresses (you can still connect to Unix domain sockets manually). This also disables all DNS lookups, to avoid leaking information.
'';
};
- bind-addr = mkOption {
- type = nbPkgs.lib.ipv4Address;
- default = "127.0.0.1";
- description = "Set an IP address or UNIX domain socket to listen to";
- };
- bindport = mkOption {
- type = types.port;
- default = 9735;
- description = "Set a Port to listen to locally";
- };
announce-tor = mkOption {
type = types.bool;
default = false;
diff --git a/modules/modules.nix b/modules/modules.nix
index fb366dd1d..9c2b18dab 100644
--- a/modules/modules.nix
+++ b/modules/modules.nix
@@ -58,7 +58,7 @@ with lib;
config = {
assertions = [
- { assertion = (config.services.lnd.enable -> ( !config.services.clightning.enable || config.services.clightning.bindport != config.services.lnd.port));
+ { assertion = (config.services.lnd.enable -> ( !config.services.clightning.enable || config.services.clightning.port != config.services.lnd.port));
message = ''
LND and clightning can't both bind to lightning port 9735. Either
disable LND/clightning or change services.clightning.bindPort or
diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix
index 47bf3f113..03501c6b7 100644
--- a/modules/netns-isolation.nix
+++ b/modules/netns-isolation.nix
@@ -254,7 +254,7 @@ in {
};
systemd.services.bitcoind-import-banlist.serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-bitcoind";
- services.clightning.bind-addr = netns.clightning.address;
+ services.clightning.address = netns.clightning.address;
services.lnd = {
address = netns.lnd.address;
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 87b59be8e..9417bcc71 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -68,8 +68,8 @@ in {
services.clightning.enforceTor = true;
services.tor.hiddenServices.clightning = mkIf cfg.clightning.enable (mkHiddenService {
port = cfg.clightning.onionport;
- toHost = cfg.clightning.bind-addr;
- toPort = cfg.clightning.bindport;
+ toHost = cfg.clightning.address;
+ toPort = cfg.clightning.port;
});
# lnd
From 8fa32b7f91523ac6c499c036931d03f98b39be05 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:05 +0100
Subject: [PATCH 05/32] btcpayserver: add consistent address options
---
modules/btcpayserver.nix | 46 ++++++++++++++++-----------------
modules/netns-isolation.nix | 4 +--
modules/presets/secure-node.nix | 2 +-
3 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix
index 949cbce75..3600930a1 100644
--- a/modules/btcpayserver.nix
+++ b/modules/btcpayserver.nix
@@ -14,6 +14,16 @@ in {
default = nbPkgs.nbxplorer;
description = "The package providing nbxplorer binaries.";
};
+ address = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = "Address to listen on.";
+ };
+ port = mkOption {
+ type = types.port;
+ default = 24444;
+ description = "Port to listen on.";
+ };
dataDir = mkOption {
type = types.path;
default = "/var/lib/nbxplorer";
@@ -29,16 +39,6 @@ in {
default = cfg.nbxplorer.user;
description = "The group as which to run nbxplorer.";
};
- bind = mkOption {
- type = types.str;
- default = "127.0.0.1";
- description = "The address on which to bind.";
- };
- port = mkOption {
- type = types.port;
- default = 24444;
- description = "Port on which to bind.";
- };
enable = mkOption {
# This option is only used by netns-isolation
internal = true;
@@ -49,6 +49,16 @@ in {
btcpayserver = {
enable = mkEnableOption "btcpayserver";
+ address = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = "Address to listen on.";
+ };
+ port = mkOption {
+ type = types.port;
+ default = 23000;
+ description = "Port to listen on.";
+ };
package = mkOption {
type = types.package;
default = nbPkgs.btcpayserver;
@@ -69,16 +79,6 @@ in {
default = cfg.btcpayserver.user;
description = "The group as which to run btcpayserver.";
};
- bind = mkOption {
- type = types.str;
- default = "127.0.0.1";
- description = "The address on which to bind.";
- };
- port = mkOption {
- type = types.port;
- default = 23000;
- description = "Port on which to bind.";
- };
lightningBackend = mkOption {
type = types.nullOr (types.enum [ "clightning" "lnd" ]);
default = null;
@@ -119,7 +119,7 @@ in {
btcrpcuser=${cfg.bitcoind.rpc.users.btcpayserver.name}
btcrpcurl=http://${config.services.bitcoind.rpc.address}:${toString cfg.bitcoind.rpc.port}
btcnodeendpoint=${config.services.bitcoind.address}:${toString config.services.bitcoind.port}
- bind=${cfg.nbxplorer.bind}
+ bind=${cfg.nbxplorer.address}
port=${toString cfg.nbxplorer.port}
'';
in {
@@ -153,9 +153,9 @@ in {
network=${config.services.bitcoind.network}
postgres=User ID=${cfg.btcpayserver.user};Host=/run/postgresql;Database=btcpaydb
socksendpoint=${cfg.tor.client.socksListenAddress}
- btcexplorerurl=http://${cfg.nbxplorer.bind}:${toString cfg.nbxplorer.port}/
+ btcexplorerurl=http://${cfg.nbxplorer.address}:${toString cfg.nbxplorer.port}/
btcexplorercookiefile=${cfg.nbxplorer.dataDir}/${config.services.bitcoind.makeNetworkName "Main" "RegTest"}/.cookie
- bind=${cfg.btcpayserver.bind}
+ bind=${cfg.btcpayserver.address}
${optionalString (cfg.btcpayserver.rootpath != null) "rootpath=${cfg.btcpayserver.rootpath}"}
port=${toString cfg.btcpayserver.port}
'' + optionalString (cfg.btcpayserver.lightningBackend == "clightning") ''
diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix
index 03501c6b7..529d745ff 100644
--- a/modules/netns-isolation.nix
+++ b/modules/netns-isolation.nix
@@ -280,8 +280,8 @@ in {
services.lightning-loop.rpcAddress = netns.lightning-loop.address;
- services.nbxplorer.bind = netns.nbxplorer.address;
- services.btcpayserver.bind = netns.btcpayserver.address;
+ services.nbxplorer.address = netns.nbxplorer.address;
+ services.btcpayserver.address = netns.btcpayserver.address;
services.joinmarket.cliExec = mkCliExec "joinmarket";
systemd.services.joinmarket-yieldgenerator.serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-joinmarket";
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 9417bcc71..8a6bda2fb 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -103,7 +103,7 @@ in {
# disable tor enforcement until btcpayserver can fetch rates over Tor
services.btcpayserver.enforceTor = false;
services.nbxplorer.enforceTor = true;
- services.tor.hiddenServices.btcpayserver = mkIf cfg.btcpayserver.enable (mkHiddenService { port = 80; toPort = 23000; toHost = cfg.btcpayserver.bind; });
+ services.tor.hiddenServices.btcpayserver = mkIf cfg.btcpayserver.enable (mkHiddenService { port = 80; toPort = 23000; toHost = cfg.btcpayserver.address; });
services.spark-wallet = {
onion-service = true;
From b5d76ba1b3cb3c0683a4b0e2feac8aa722966193 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:06 +0100
Subject: [PATCH 06/32] electrs: add consistent address options
---
modules/electrs.nix | 20 ++++++++++----------
modules/presets/secure-node.nix | 1 -
2 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/modules/electrs.nix b/modules/electrs.nix
index b503908ef..5d03c10f0 100644
--- a/modules/electrs.nix
+++ b/modules/electrs.nix
@@ -9,6 +9,16 @@ let
in {
options.services.electrs = {
enable = mkEnableOption "electrs";
+ address = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = "Address to listen for RPC connections.";
+ };
+ port = mkOption {
+ type = types.port;
+ default = 50001;
+ description = "RPC port.";
+ };
dataDir = mkOption {
type = types.path;
default = "/var/lib/electrs";
@@ -31,16 +41,6 @@ in {
If enabled, the electrs service will sync faster on high-memory systems (≥ 8GB).
'';
};
- address = mkOption {
- type = types.str;
- default = "127.0.0.1";
- description = "RPC and monitoring listening address.";
- };
- port = mkOption {
- type = types.port;
- default = 50001;
- description = "RPC port.";
- };
monitoringPort = mkOption {
type = types.port;
default = 4224;
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 8a6bda2fb..6c0c95aac 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -92,7 +92,6 @@ in {
# electrs
services.electrs = {
- port = 50001;
enforceTor = true;
};
services.tor.hiddenServices.electrs = mkIf cfg.electrs.enable (mkHiddenService {
From 39f16c0b4aab844b183ee4c97acebf95eb2fe1c0 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:07 +0100
Subject: [PATCH 07/32] liquidd: add consistent address options
---
modules/liquid.nix | 54 ++++++++++++++-------------------
modules/netns-isolation.nix | 4 +--
modules/presets/secure-node.nix | 3 +-
3 files changed, 26 insertions(+), 35 deletions(-)
diff --git a/modules/liquid.nix b/modules/liquid.nix
index 954b00601..354e17921 100644
--- a/modules/liquid.nix
+++ b/modules/liquid.nix
@@ -16,19 +16,19 @@ let
${optionalString (cfg.validatepegin != null) "validatepegin=${if cfg.validatepegin then "1" else "0"}"}
# Connection options
- ${optionalString cfg.listen "bind=${cfg.bind}"}
- ${optionalString (cfg.port != null) "port=${toString cfg.port}"}
+ ${optionalString cfg.listen "bind=${cfg.address}"}
+ port=${toString cfg.port}
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
listen=${if cfg.listen then "1" else "0"}
# RPC server options
- ${optionalString (cfg.rpc.port != null) "rpcport=${toString cfg.rpc.port}"}
+ rpcport=${toString cfg.rpc.port}
${concatMapStringsSep "\n"
(rpcUser: "rpcauth=${rpcUser.name}:${rpcUser.passwordHMAC}")
(attrValues cfg.rpc.users)
}
- rpcbind=${cfg.rpcbind}
- rpcconnect=${cfg.rpcbind}
+ rpcbind=${cfg.rpc.address}
+ rpcconnect=${cfg.rpc.address}
${lib.concatMapStrings (rpcallowip: "rpcallowip=${rpcallowip}\n") cfg.rpcallowip}
${optionalString (cfg.rpcuser != null) "rpcuser=${cfg.rpcuser}"}
${optionalString (cfg.rpcpassword != null) "rpcpassword=${cfg.rpcpassword}"}
@@ -71,7 +71,16 @@ in {
services.liquidd = {
enable = mkEnableOption "Liquid sidechain";
-
+ address = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = "Address to listen for peer connections.";
+ };
+ port = mkOption {
+ type = types.port;
+ default = 7042;
+ description = "Override the default port on which to listen for connections.";
+ };
extraConfig = mkOption {
type = types.lines;
default = "";
@@ -88,14 +97,6 @@ in {
default = "/var/lib/liquidd";
description = "The data directory for liquidd.";
};
- bind = mkOption {
- type = types.str;
- default = "127.0.0.1";
- description = ''
- Bind to given address and always listen on it.
- '';
- };
-
user = mkOption {
type = types.str;
default = "liquid";
@@ -106,12 +107,16 @@ in {
default = cfg.user;
description = "The group as which to run liquidd.";
};
-
rpc = {
+ address = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = "Address to listen for JSON-RPC connections.";
+ };
port = mkOption {
- type = types.nullOr types.port;
- default = null;
- description = "Override the default port on which to listen for JSON-RPC connections.";
+ type = types.port;
+ default = 7041;
+ description = "Port to listen for JSON-RPC connections.";
};
users = mkOption {
default = {};
@@ -125,14 +130,6 @@ in {
'';
};
};
-
- rpcbind = mkOption {
- type = types.str;
- default = "127.0.0.1";
- description = ''
- Bind to given address to listen for JSON-RPC connections.
- '';
- };
rpcallowip = mkOption {
type = types.listOf types.str;
default = [ "127.0.0.1" ];
@@ -155,11 +152,6 @@ in {
default = false;
description = "Whether to use the test chain.";
};
- port = mkOption {
- type = types.nullOr types.port;
- default = null;
- description = "Override the default port on which to listen for connections.";
- };
proxy = mkOption {
type = types.nullOr types.str;
default = if cfg.enforceTor then config.services.tor.client.socksListenAddress else null;
diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix
index 529d745ff..e417fcce7 100644
--- a/modules/netns-isolation.nix
+++ b/modules/netns-isolation.nix
@@ -263,8 +263,8 @@ in {
};
services.liquidd = {
- bind = netns.liquidd.address;
- rpcbind = netns.liquidd.address;
+ address = netns.liquidd.address;
+ rpc.address = netns.liquidd.address;
rpcallowip = [
bridgeIp # For operator user
netns.liquidd.address
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 6c0c95aac..91f612297 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -86,9 +86,8 @@ in {
validatepegin = true;
listen = true;
enforceTor = true;
- port = 7042;
};
- services.tor.hiddenServices.liquidd = mkIf cfg.liquidd.enable (mkHiddenService { port = cfg.liquidd.port; toHost = cfg.liquidd.bind; });
+ services.tor.hiddenServices.liquidd = mkIf cfg.liquidd.enable (mkHiddenService { port = cfg.liquidd.port; toHost = cfg.liquidd.address; });
# electrs
services.electrs = {
From 09e0042aa84b5effa746d9cf76fd06b3a97ad06c Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:08 +0100
Subject: [PATCH 08/32] spark-wallet: add consistent address options
---
modules/netns-isolation.nix | 2 +-
modules/spark-wallet.nix | 13 +++++++++----
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix
index e417fcce7..36e5300f3 100644
--- a/modules/netns-isolation.nix
+++ b/modules/netns-isolation.nix
@@ -274,7 +274,7 @@ in {
services.electrs.address = netns.electrs.address;
services.spark-wallet = {
- host = netns.spark-wallet.address;
+ address = netns.spark-wallet.address;
extraArgs = "--no-tls";
};
diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix
index 6f9ca684a..091fb2388 100644
--- a/modules/spark-wallet.nix
+++ b/modules/spark-wallet.nix
@@ -16,7 +16,7 @@ let
''}
exec ${config.nix-bitcoin.pkgs.spark-wallet}/bin/spark-wallet \
--ln-path '${config.services.clightning.networkDir}' \
- --host ${cfg.host} \
+ --host ${cfg.address} --port ${toString cfg.port} \
--config '${config.nix-bitcoin.secretsDir}/spark-wallet-login' \
${optionalString cfg.enforceTor torRateProvider} \
$publicURL \
@@ -31,10 +31,15 @@ in {
If enabled, the spark-wallet service will be installed.
'';
};
- host = mkOption {
+ address = mkOption {
type = types.str;
default = "localhost";
- description = "http(s) server listen address.";
+ description = "http(s) server address.";
+ };
+ port = mkOption {
+ type = types.port;
+ default = 9737;
+ description = "http(s) server port.";
};
onion-service = mkOption {
type = types.bool;
@@ -63,7 +68,7 @@ in {
services.tor.hiddenServices.spark-wallet = mkIf cfg.onion-service {
map = [{
- port = 80; toPort = 9737; toHost = cfg.host;
+ port = 80; toPort = cfg.port; toHost = cfg.address;
}];
version = 3;
};
From 55073eee70056b2850656cb3db1b62068b726267 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:09 +0100
Subject: [PATCH 09/32] remove nix-bitcoin.pkgs.lib
Type ipv4Address is not needed anymore because all services have
separate 'port' and 'address' options.
---
pkgs/default.nix | 2 --
pkgs/lib.nix | 5 -----
2 files changed, 7 deletions(-)
delete mode 100644 pkgs/lib.nix
diff --git a/pkgs/default.nix b/pkgs/default.nix
index 639b6b2ff..db178c1ed 100644
--- a/pkgs/default.nix
+++ b/pkgs/default.nix
@@ -20,7 +20,5 @@ let self = {
pinned = import ./pinned.nix;
- lib = import ./lib.nix { inherit (pkgs) lib; };
-
modulesPkgs = self // self.pinned;
}; in self
diff --git a/pkgs/lib.nix b/pkgs/lib.nix
deleted file mode 100644
index 43dbe4507..000000000
--- a/pkgs/lib.nix
+++ /dev/null
@@ -1,5 +0,0 @@
-{ lib }:
-{
- # An address type that checks that there's no port
- ipv4Address = lib.types.addCheck lib.types.str (s: builtins.length (builtins.split ":" s) == 1);
-}
From 5c6977b006d492ac7030373129ddb989e0691847 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:10 +0100
Subject: [PATCH 10/32] rename onion-chef -> nix-bitcoin.onionAddresses
This clarifies its function.
---
modules/clightning.nix | 10 +++----
modules/lnd.nix | 10 +++----
modules/modules.nix | 2 +-
modules/nodeinfo.nix | 16 +++++------
.../{onion-chef.nix => onion-addresses.nix} | 27 ++++++++++---------
modules/presets/secure-node.nix | 2 +-
modules/spark-wallet.nix | 14 +++++-----
test/tests.py | 2 +-
8 files changed, 42 insertions(+), 41 deletions(-)
rename modules/{onion-chef.nix => onion-addresses.nix} (73%)
diff --git a/modules/clightning.nix b/modules/clightning.nix
index 23f2307f5..fa621c4c7 100644
--- a/modules/clightning.nix
+++ b/modules/clightning.nix
@@ -6,7 +6,7 @@ let
cfg = config.services.clightning;
inherit (config) nix-bitcoin-services;
nbPkgs = config.nix-bitcoin.pkgs;
- onion-chef-service = (if cfg.announce-tor then [ "onion-chef.service" ] else []);
+ onionAddressesService = (if cfg.announce-tor then [ "onion-addresses.service" ] else []);
network = config.services.bitcoind.makeNetworkName "bitcoin" "regtest";
configFile = pkgs.writeText "config" ''
network=${network}
@@ -108,13 +108,13 @@ in {
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
];
- services.onion-chef.access.clightning = if cfg.announce-tor then [ "clightning" ] else [];
+ nix-bitcoin.onionAddresses.access.clightning = if cfg.announce-tor then [ "clightning" ] else [];
systemd.services.clightning = {
description = "Run clightningd";
path = [ nbPkgs.bitcoind ];
wantedBy = [ "multi-user.target" ];
- requires = [ "bitcoind.service" ] ++ onion-chef-service;
- after = [ "bitcoind.service" ] ++ onion-chef-service;
+ requires = [ "bitcoind.service" ] ++ onionAddressesService;
+ after = [ "bitcoind.service" ] ++ onionAddressesService;
preStart = ''
cp ${configFile} ${cfg.dataDir}/config
chown -R '${cfg.user}:${cfg.group}' '${cfg.dataDir}'
@@ -122,7 +122,7 @@ in {
rm -f ${cfg.networkDir}/lightning-rpc
chmod 640 ${cfg.dataDir}/config
echo "bitcoin-rpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-public)" >> '${cfg.dataDir}/config'
- ${optionalString cfg.announce-tor "echo announce-addr=$(cat /var/lib/onion-chef/clightning/clightning) >> '${cfg.dataDir}/config'"}
+ ${optionalString cfg.announce-tor "echo announce-addr=$(cat /var/lib/onion-addresses/clightning/clightning) >> '${cfg.dataDir}/config'"}
'';
serviceConfig = nix-bitcoin-services.defaultHardening // {
ExecStart = "${nbPkgs.clightning}/bin/lightningd --lightning-dir=${cfg.dataDir}";
diff --git a/modules/lnd.nix b/modules/lnd.nix
index 226b60c7d..05fe9f6e8 100644
--- a/modules/lnd.nix
+++ b/modules/lnd.nix
@@ -9,7 +9,7 @@ let
bitcoind = config.services.bitcoind;
bitcoindRpcAddress = bitcoind.rpc.address;
- onion-chef-service = (if cfg.announce-tor then [ "onion-chef.service" ] else []);
+ onionAddressesService = (if cfg.announce-tor then [ "onion-addresses.service" ] else []);
networkDir = "${cfg.dataDir}/chain/bitcoin/${bitcoind.network}";
configFile = pkgs.writeText "lnd.conf" ''
datadir=${cfg.dataDir}
@@ -165,16 +165,16 @@ in {
zmqpubrawtx = "tcp://${bitcoindRpcAddress}:28333";
};
- services.onion-chef.access.lnd = if cfg.announce-tor then [ "lnd" ] else [];
+ nix-bitcoin.onionAddresses.access.lnd = if cfg.announce-tor then [ "lnd" ] else [];
systemd.services.lnd = {
description = "Run LND";
wantedBy = [ "multi-user.target" ];
- requires = [ "bitcoind.service" ] ++ onion-chef-service;
- after = [ "bitcoind.service" ] ++ onion-chef-service;
+ requires = [ "bitcoind.service" ] ++ onionAddressesService;
+ after = [ "bitcoind.service" ] ++ onionAddressesService;
preStart = ''
install -m600 ${configFile} '${cfg.dataDir}/lnd.conf'
echo "bitcoind.rpcpass=$(cat ${secretsDir}/bitcoin-rpcpassword-public)" >> '${cfg.dataDir}/lnd.conf'
- ${optionalString cfg.announce-tor "echo externalip=$(cat /var/lib/onion-chef/lnd/lnd) >> '${cfg.dataDir}/lnd.conf'"}
+ ${optionalString cfg.announce-tor "echo externalip=$(cat /var/lib/onion-addresses/lnd/lnd) >> '${cfg.dataDir}/lnd.conf'"}
'';
serviceConfig = nix-bitcoin-services.defaultHardening // {
RuntimeDirectory = "lnd"; # Only used to store custom macaroons
diff --git a/modules/modules.nix b/modules/modules.nix
index 9c2b18dab..878b4c657 100644
--- a/modules/modules.nix
+++ b/modules/modules.nix
@@ -24,9 +24,9 @@ with lib;
# Support features
./versioning.nix
./security.nix
+ ./onion-addresses.nix
./netns-isolation.nix
./backups.nix
- ./onion-chef.nix
];
disabledModules = [ "services/networking/bitcoind.nix" ];
diff --git a/modules/nodeinfo.nix b/modules/nodeinfo.nix
index 86f417416..254ad0609 100644
--- a/modules/nodeinfo.nix
+++ b/modules/nodeinfo.nix
@@ -7,12 +7,12 @@ let
script = pkgs.writeScriptBin "nodeinfo" ''
set -eo pipefail
- BITCOIND_ONION="$(cat /var/lib/onion-chef/${operatorName}/bitcoind)"
+ BITCOIND_ONION="$(cat /var/lib/onion-addresses/${operatorName}/bitcoind)"
echo BITCOIND_ONION="$BITCOIND_ONION"
if systemctl is-active --quiet clightning; then
CLIGHTNING_NODEID=$(lightning-cli getinfo | jq -r '.id')
- CLIGHTNING_ONION="$(cat /var/lib/onion-chef/${operatorName}/clightning)"
+ CLIGHTNING_ONION="$(cat /var/lib/onion-addresses/${operatorName}/clightning)"
CLIGHTNING_ID="$CLIGHTNING_NODEID@$CLIGHTNING_ONION:9735"
echo CLIGHTNING_NODEID="$CLIGHTNING_NODEID"
echo CLIGHTNING_ONION="$CLIGHTNING_ONION"
@@ -24,37 +24,37 @@ let
echo LND_NODEID="$LND_NODEID"
fi
- NGINX_ONION_FILE=/var/lib/onion-chef/${operatorName}/nginx
+ NGINX_ONION_FILE=/var/lib/onion-addresses/${operatorName}/nginx
if [ -e "$NGINX_ONION_FILE" ]; then
NGINX_ONION="$(cat $NGINX_ONION_FILE)"
echo NGINX_ONION="$NGINX_ONION"
fi
- LIQUIDD_ONION_FILE=/var/lib/onion-chef/${operatorName}/liquidd
+ LIQUIDD_ONION_FILE=/var/lib/onion-addresses/${operatorName}/liquidd
if [ -e "$LIQUIDD_ONION_FILE" ]; then
LIQUIDD_ONION="$(cat $LIQUIDD_ONION_FILE)"
echo LIQUIDD_ONION="$LIQUIDD_ONION"
fi
- SPARKWALLET_ONION_FILE=/var/lib/onion-chef/${operatorName}/spark-wallet
+ SPARKWALLET_ONION_FILE=/var/lib/onion-addresses/${operatorName}/spark-wallet
if [ -e "$SPARKWALLET_ONION_FILE" ]; then
SPARKWALLET_ONION="$(cat $SPARKWALLET_ONION_FILE)"
echo SPARKWALLET_ONION="http://$SPARKWALLET_ONION"
fi
- ELECTRS_ONION_FILE=/var/lib/onion-chef/${operatorName}/electrs
+ ELECTRS_ONION_FILE=/var/lib/onion-addresses/${operatorName}/electrs
if [ -e "$ELECTRS_ONION_FILE" ]; then
ELECTRS_ONION="$(cat $ELECTRS_ONION_FILE)"
echo ELECTRS_ONION="$ELECTRS_ONION"
fi
- BTCPAYSERVER_ONION_FILE=/var/lib/onion-chef/${operatorName}/btcpayserver
+ BTCPAYSERVER_ONION_FILE=/var/lib/onion-addresses/${operatorName}/btcpayserver
if [ -e "$BTCPAYSERVER_ONION_FILE" ]; then
BTCPAYSERVER_ONION="$(cat $BTCPAYSERVER_ONION_FILE)"
echo BTCPAYSERVER_ONION="$BTCPAYSERVER_ONION"
fi
- SSHD_ONION_FILE=/var/lib/onion-chef/${operatorName}/sshd
+ SSHD_ONION_FILE=/var/lib/onion-addresses/${operatorName}/sshd
if [ -e "$SSHD_ONION_FILE" ]; then
SSHD_ONION="$(cat $SSHD_ONION_FILE)"
echo SSHD_ONION="$SSHD_ONION"
diff --git a/modules/onion-chef.nix b/modules/onion-addresses.nix
similarity index 73%
rename from modules/onion-chef.nix
rename to modules/onion-addresses.nix
index 2fe383943..01d6ba0ce 100644
--- a/modules/onion-chef.nix
+++ b/modules/onion-addresses.nix
@@ -1,17 +1,18 @@
-# The onion chef module allows unprivileged users to read onion hostnames.
-# By default the onion hostnames in /var/lib/tor/onion are only readable by the
-# tor user. The onion chef copies the onion hostnames into into
-# /var/lib/onion-chef and sets permissions according to the access option.
+# This module enables unprivileged users to read onion addresses.
+# By default, onion addresses in /var/lib/tor/onion are only readable by the
+# tor user.
+# The included service copies onion addresses to /var/lib/onion-addresses//
+# and sets permissions according to option 'access'.
{ config, lib, pkgs, ... }:
with lib;
let
- cfg = config.services.onion-chef;
+ cfg = config.nix-bitcoin.onionAddresses;
inherit (config) nix-bitcoin-services;
- dataDir = "/var/lib/onion-chef/";
- onion-chef-script = pkgs.writeScript "onion-chef.sh" ''
+ dataDir = "/var/lib/onion-addresses/";
+ onion-addresses-script = pkgs.writeScript "onion-addresses.sh" ''
# wait until tor is up
until ls -l /var/lib/tor/state; do sleep 1; done
@@ -42,12 +43,12 @@ let
}
'';
in {
- options.services.onion-chef = {
+ options.nix-bitcoin.onionAddresses = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
- If enabled, the onion-chef service will be installed.
+ If enabled, the onion-addresses service will be installed.
'';
};
access = mkOption {
@@ -61,7 +62,7 @@ in {
"operator" = [ "bitcoind" "clightning" ];
};
The onion hostnames can then be read from
- /var/lib/onion-chef/.
+ /var/lib/onion-addresses/.
'';
};
};
@@ -71,13 +72,13 @@ in {
"d '${dataDir}' 0755 root root - -"
];
- systemd.services.onion-chef = {
- description = "Run onion-chef";
+ systemd.services.onion-addresses = {
+ description = "Run onion-addresses";
wantedBy = [ "tor.service" ];
bindsTo = [ "tor.service" ];
after = [ "tor.service" ];
serviceConfig = nix-bitcoin-services.defaultHardening // {
- ExecStart = "${pkgs.bash}/bin/bash ${onion-chef-script}";
+ ExecStart = "${pkgs.bash}/bin/bash ${onion-addresses-script}";
Type = "oneshot";
RemainAfterExit = true;
PrivateNetwork = "true"; # This service needs no network access
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 91f612297..8d7716077 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -124,7 +124,7 @@ in {
qrencode
];
- services.onion-chef = {
+ nix-bitcoin.onionAddresses = {
enable = true;
access.${operatorName} = [ "bitcoind" "clightning" "nginx" "liquidd" "spark-wallet" "electrs" "btcpayserver" "sshd" ];
};
diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix
index 091fb2388..0e2a12d96 100644
--- a/modules/spark-wallet.nix
+++ b/modules/spark-wallet.nix
@@ -5,14 +5,14 @@ with lib;
let
cfg = config.services.spark-wallet;
inherit (config) nix-bitcoin-services;
- onion-chef-service = (if cfg.onion-service then [ "onion-chef.service" ] else []);
+ onionAddressesService = (if cfg.onion-service then [ "onion-addresses.service" ] else []);
# Use wasabi rate provider because the default (bitstamp) doesn't accept
# connections through Tor
torRateProvider = "--rate-provider wasabi --proxy socks5h://${config.services.tor.client.socksListenAddress}";
startScript = ''
${optionalString cfg.onion-service ''
- publicURL="--public-url http://$(cat /var/lib/onion-chef/spark-wallet/spark-wallet)"
+ publicURL="--public-url http://$(cat /var/lib/onion-addresses/spark-wallet/spark-wallet)"
''}
exec ${config.nix-bitcoin.pkgs.spark-wallet}/bin/spark-wallet \
--ln-path '${config.services.clightning.networkDir}' \
@@ -72,19 +72,19 @@ in {
}];
version = 3;
};
- services.onion-chef.enable = cfg.onion-service;
- services.onion-chef.access.spark-wallet = if cfg.onion-service then [ "spark-wallet" ] else [];
+ nix-bitcoin.onionAddresses.enable = cfg.onion-service;
+ nix-bitcoin.onionAddresses.access.spark-wallet = if cfg.onion-service then [ "spark-wallet" ] else [];
systemd.services.spark-wallet = {
description = "Run spark-wallet";
wantedBy = [ "multi-user.target" ];
- requires = [ "clightning.service" ] ++ onion-chef-service;
- after = [ "clightning.service" ] ++ onion-chef-service;
+ requires = [ "clightning.service" ] ++ onionAddressesService;
+ after = [ "clightning.service" ] ++ onionAddressesService;
script = startScript;
serviceConfig = nix-bitcoin-services.defaultHardening // {
User = "spark-wallet";
Restart = "on-failure";
RestartSec = "10s";
- ReadWritePaths = mkIf cfg.onion-service "/var/lib/onion-chef";
+ ReadWritePaths = mkIf cfg.onion-service "/var/lib/onion-addresses";
} // (if cfg.enforceTor
then nix-bitcoin-services.allowTor
else nix-bitcoin-services.allowAnyIP)
diff --git a/test/tests.py b/test/tests.py
index 53165ed8d..18afd1eff 100644
--- a/test/tests.py
+++ b/test/tests.py
@@ -218,7 +218,7 @@ def _():
@test("secure-node")
def _():
- assert_running("onion-chef")
+ assert_running("onion-addresses")
# FIXME: use 'wait_for_unit' because 'create-web-index' always fails during startup due
# to incomplete unit dependencies.
From 43c247e3fe3b2a8f635373a4278ba990694b330a Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:11 +0100
Subject: [PATCH 11/32] onionAddresses: use StateDirectory instead of tmpfiles
Simplifies the dataDir setup.
---
modules/onion-addresses.nix | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/modules/onion-addresses.nix b/modules/onion-addresses.nix
index 01d6ba0ce..27d20e361 100644
--- a/modules/onion-addresses.nix
+++ b/modules/onion-addresses.nix
@@ -68,10 +68,6 @@ in {
};
config = mkIf cfg.enable {
- systemd.tmpfiles.rules = [
- "d '${dataDir}' 0755 root root - -"
- ];
-
systemd.services.onion-addresses = {
description = "Run onion-addresses";
wantedBy = [ "tor.service" ];
@@ -81,9 +77,9 @@ in {
ExecStart = "${pkgs.bash}/bin/bash ${onion-addresses-script}";
Type = "oneshot";
RemainAfterExit = true;
+ StateDirectory = "onion-addresses";
PrivateNetwork = "true"; # This service needs no network access
PrivateUsers = "false";
- ReadWritePaths = "${dataDir}";
CapabilityBoundingSet = "CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_IPC_OWNER";
};
};
From 93562f76dd0da0ccc77e71e522fb75332ed674ed Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:12 +0100
Subject: [PATCH 12/32] onionAddresses: remove redundant option 'enable'
The service can be disabled via `onion-addresses.access = mkForce {};`
Also remove redundant description.
---
modules/onion-addresses.nix | 10 +---------
modules/presets/secure-node.nix | 1 -
modules/spark-wallet.nix | 1 -
3 files changed, 1 insertion(+), 11 deletions(-)
diff --git a/modules/onion-addresses.nix b/modules/onion-addresses.nix
index 27d20e361..65809ea44 100644
--- a/modules/onion-addresses.nix
+++ b/modules/onion-addresses.nix
@@ -44,13 +44,6 @@ let
'';
in {
options.nix-bitcoin.onionAddresses = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description = ''
- If enabled, the onion-addresses service will be installed.
- '';
- };
access = mkOption {
type = types.attrs;
default = {};
@@ -67,9 +60,8 @@ in {
};
};
- config = mkIf cfg.enable {
+ config = mkIf (cfg.access != {}) {
systemd.services.onion-addresses = {
- description = "Run onion-addresses";
wantedBy = [ "tor.service" ];
bindsTo = [ "tor.service" ];
after = [ "tor.service" ];
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 8d7716077..570c6c025 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -125,7 +125,6 @@ in {
];
nix-bitcoin.onionAddresses = {
- enable = true;
access.${operatorName} = [ "bitcoind" "clightning" "nginx" "liquidd" "spark-wallet" "electrs" "btcpayserver" "sshd" ];
};
diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix
index 0e2a12d96..52bcee1bd 100644
--- a/modules/spark-wallet.nix
+++ b/modules/spark-wallet.nix
@@ -72,7 +72,6 @@ in {
}];
version = 3;
};
- nix-bitcoin.onionAddresses.enable = cfg.onion-service;
nix-bitcoin.onionAddresses.access.spark-wallet = if cfg.onion-service then [ "spark-wallet" ] else [];
systemd.services.spark-wallet = {
description = "Run spark-wallet";
From 6d13b26d0a5d42821028ce999653cff3771a3cc9 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:13 +0100
Subject: [PATCH 13/32] onionAddresses: add more precise type for option
'access'
---
modules/onion-addresses.nix | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/modules/onion-addresses.nix b/modules/onion-addresses.nix
index 65809ea44..302479ebc 100644
--- a/modules/onion-addresses.nix
+++ b/modules/onion-addresses.nix
@@ -45,17 +45,17 @@ let
in {
options.nix-bitcoin.onionAddresses = {
access = mkOption {
- type = types.attrs;
+ type = with types; attrsOf (listOf str);
default = {};
description = ''
- This option controls who is allowed to access onion hostnames. For
- example the following allows the user operator to access the bitcoind
- and clightning onion.
+ This option controls who is allowed to access onion addresses.
+ For example, the following allows user 'myuser' to access bitcoind
+ and clightning onion addresses:
{
- "operator" = [ "bitcoind" "clightning" ];
+ "myuser" = [ "bitcoind" "clightning" ];
};
The onion hostnames can then be read from
- /var/lib/onion-addresses/.
+ /var/lib/onion-addresses/myuser.
'';
};
};
From b266f232515ce64354d22271ffba9dca8496a67f Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:14 +0100
Subject: [PATCH 14/32] onionAddresses: use service 'script' option
This also makes the script stop on errors.
---
modules/onion-addresses.nix | 63 ++++++++++++++++++-------------------
1 file changed, 31 insertions(+), 32 deletions(-)
diff --git a/modules/onion-addresses.nix b/modules/onion-addresses.nix
index 302479ebc..e35e5202b 100644
--- a/modules/onion-addresses.nix
+++ b/modules/onion-addresses.nix
@@ -4,7 +4,7 @@
# The included service copies onion addresses to /var/lib/onion-addresses//
# and sets permissions according to option 'access'.
-{ config, lib, pkgs, ... }:
+{ config, lib, ... }:
with lib;
@@ -12,36 +12,6 @@ let
cfg = config.nix-bitcoin.onionAddresses;
inherit (config) nix-bitcoin-services;
dataDir = "/var/lib/onion-addresses/";
- onion-addresses-script = pkgs.writeScript "onion-addresses.sh" ''
- # wait until tor is up
- until ls -l /var/lib/tor/state; do sleep 1; done
-
- cd ${dataDir}
-
- # Create directory for every user and set permissions
- ${ builtins.foldl'
- (x: user: x +
- ''
- mkdir -p -m 0700 ${user}
- chown ${user} ${user}
- # Copy onion hostnames into the user's directory
- ${ builtins.foldl'
- (x: onion: x +
- ''
- ONION_FILE=/var/lib/tor/onion/${onion}/hostname
- if [ -e "$ONION_FILE" ]; then
- cp $ONION_FILE ${user}/${onion}
- chown ${user} ${user}/${onion}
- fi
- '')
- ""
- (builtins.getAttr user cfg.access)
- }
- '')
- ""
- (builtins.attrNames cfg.access)
- }
- '';
in {
options.nix-bitcoin.onionAddresses = {
access = mkOption {
@@ -66,7 +36,6 @@ in {
bindsTo = [ "tor.service" ];
after = [ "tor.service" ];
serviceConfig = nix-bitcoin-services.defaultHardening // {
- ExecStart = "${pkgs.bash}/bin/bash ${onion-addresses-script}";
Type = "oneshot";
RemainAfterExit = true;
StateDirectory = "onion-addresses";
@@ -74,6 +43,36 @@ in {
PrivateUsers = "false";
CapabilityBoundingSet = "CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_IPC_OWNER";
};
+ script = ''
+ # wait until tor is up
+ until ls -l /var/lib/tor/state; do sleep 1; done
+
+ cd ${dataDir}
+
+ # Create directory for every user and set permissions
+ ${ builtins.foldl'
+ (x: user: x +
+ ''
+ mkdir -p -m 0700 ${user}
+ chown ${user} ${user}
+ # Copy onion hostnames into the user's directory
+ ${ builtins.foldl'
+ (x: onion: x +
+ ''
+ ONION_FILE=/var/lib/tor/onion/${onion}/hostname
+ if [ -e "$ONION_FILE" ]; then
+ cp $ONION_FILE ${user}/${onion}
+ chown ${user} ${user}/${onion}
+ fi
+ '')
+ ""
+ (builtins.getAttr user cfg.access)
+ }
+ '')
+ ""
+ (builtins.attrNames cfg.access)
+ }
+ '';
};
};
}
From 5f34b094d3c13978e1689e73d679190a8f0cdcbb Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:15 +0100
Subject: [PATCH 15/32] onionAddresses: improve script
- use -e to check for existence of /var/lib/tor/state, use shorter
polling interval
- clear existing dataDir contents to avoid accumulating obsolete data
- use concatMapStrings instead of foldl'
---
modules/onion-addresses.nix | 37 ++++++++++++++++---------------------
1 file changed, 16 insertions(+), 21 deletions(-)
diff --git a/modules/onion-addresses.nix b/modules/onion-addresses.nix
index e35e5202b..905f73d4c 100644
--- a/modules/onion-addresses.nix
+++ b/modules/onion-addresses.nix
@@ -44,32 +44,27 @@ in {
CapabilityBoundingSet = "CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_IPC_OWNER";
};
script = ''
- # wait until tor is up
- until ls -l /var/lib/tor/state; do sleep 1; done
+ # Wait until tor is up
+ until [[ -e /var/lib/tor/state ]]; do sleep 0.1; done
cd ${dataDir}
+ rm -rf *
- # Create directory for every user and set permissions
- ${ builtins.foldl'
- (x: user: x +
- ''
+ ${concatMapStrings
+ (user: ''
mkdir -p -m 0700 ${user}
chown ${user} ${user}
- # Copy onion hostnames into the user's directory
- ${ builtins.foldl'
- (x: onion: x +
- ''
- ONION_FILE=/var/lib/tor/onion/${onion}/hostname
- if [ -e "$ONION_FILE" ]; then
- cp $ONION_FILE ${user}/${onion}
- chown ${user} ${user}/${onion}
- fi
- '')
- ""
- (builtins.getAttr user cfg.access)
- }
- '')
- ""
+ ${concatMapStrings
+ (service: ''
+ onionFile=/var/lib/tor/onion/${service}/hostname
+ if [[ -e $onionFile ]]; then
+ cp $onionFile ${user}/${service}
+ chown ${user} ${user}/${service}
+ fi
+ '')
+ cfg.access.${user}
+ }
+ '')
(builtins.attrNames cfg.access)
}
'';
From fffe988248fcb48fe0a58214aa96b2900c92309b Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:16 +0100
Subject: [PATCH 16/32] onionAddresses: add readonly option 'dataDir'
Used by 'onionServices' in a later commit for services that announce
their onion address.
---
modules/onion-addresses.nix | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/modules/onion-addresses.nix b/modules/onion-addresses.nix
index 905f73d4c..f71533704 100644
--- a/modules/onion-addresses.nix
+++ b/modules/onion-addresses.nix
@@ -11,7 +11,6 @@ with lib;
let
cfg = config.nix-bitcoin.onionAddresses;
inherit (config) nix-bitcoin-services;
- dataDir = "/var/lib/onion-addresses/";
in {
options.nix-bitcoin.onionAddresses = {
access = mkOption {
@@ -28,6 +27,10 @@ in {
/var/lib/onion-addresses/myuser.
'';
};
+ dataDir = mkOption {
+ readOnly = true;
+ default = "/var/lib/onion-addresses";
+ };
};
config = mkIf (cfg.access != {}) {
@@ -47,7 +50,7 @@ in {
# Wait until tor is up
until [[ -e /var/lib/tor/state ]]; do sleep 0.1; done
- cd ${dataDir}
+ cd ${cfg.dataDir}
rm -rf *
${concatMapStrings
From 05b5402bb152543ee21aec583436d35425bcc3b9 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:17 +0100
Subject: [PATCH 17/32] add nix-bitcoin.onionServices
---
modules/modules.nix | 1 +
modules/onion-services.nix | 103 +++++++++++++++++++++++++++++++++++++
2 files changed, 104 insertions(+)
create mode 100644 modules/onion-services.nix
diff --git a/modules/modules.nix b/modules/modules.nix
index 878b4c657..d2e669075 100644
--- a/modules/modules.nix
+++ b/modules/modules.nix
@@ -25,6 +25,7 @@ with lib;
./versioning.nix
./security.nix
./onion-addresses.nix
+ ./onion-services.nix
./netns-isolation.nix
./backups.nix
];
diff --git a/modules/onion-services.nix b/modules/onion-services.nix
new file mode 100644
index 000000000..7215543d3
--- /dev/null
+++ b/modules/onion-services.nix
@@ -0,0 +1,103 @@
+# This module creates onion-services for NixOS services.
+# An onion service can be enabled for every service that defines
+# options 'address', 'port' and optionally 'getPublicAddressCmd'.
+#
+# See it in use at ./presets/enable-tor.nix
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.nix-bitcoin.onionServices;
+
+ services = builtins.attrNames cfg;
+
+ activeServices = builtins.filter (service:
+ config.services.${service}.enable && cfg.${service}.enable
+ ) services;
+
+ publicServices = builtins.filter (service: cfg.${service}.public) activeServices;
+in {
+ options.nix-bitcoin.onionServices = mkOption {
+ default = {};
+ type = with types; attrsOf (submodule (
+ { config, ... }: {
+ options = {
+ enable = mkOption {
+ type = types.bool;
+ default = config.public;
+ description = ''
+ Create an onion service for the given service.
+ The service must define options 'address' and 'port'.
+ '';
+ };
+ public = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Make the onion address accessible to the service.
+ If enabled, the onion service is automatically enabled.
+ Only available for services that define option `getPublicAddressCmd`.
+ '';
+ };
+ externalPort = mkOption {
+ type = types.nullOr types.port;
+ default = null;
+ description = "Override the external port of the onion service.";
+ };
+ };
+ }
+ ));
+ };
+
+ config = mkMerge [
+ (mkIf (cfg != {}) {
+ # Define hidden services
+ services.tor = {
+ enable = true;
+ hiddenServices = genAttrs activeServices (name:
+ let
+ service = config.services.${name};
+ inherit (cfg.${name}) externalPort;
+ in {
+ map = [{
+ port = if externalPort != null then externalPort else service.port;
+ toPort = service.port;
+ toHost = if service.address == "0.0.0.0" then "127.0.0.1" else service.address;
+ }];
+ version = 3;
+ }
+ );
+ };
+
+ # Enable public services to access their own onion addresses
+ nix-bitcoin.onionAddresses.access = (
+ genAttrs publicServices singleton
+ ) // {
+ # Allow the operator user to access onion addresses for all active services
+ ${config.nix-bitcoin.operator.name} = mkIf config.nix-bitcoin.operator.enable activeServices;
+ };
+ systemd.services = let
+ onionAddresses = [ "onion-addresses.service" ];
+ in genAttrs publicServices (service: {
+ requires = onionAddresses;
+ after = onionAddresses;
+ });
+ })
+
+ # Set getPublicAddressCmd for public services
+ {
+ services = let
+ # publicServices' doesn't depend on config.services.*.enable,
+ # so we can use it to define config.services without causing infinite recursion
+ publicServices' = builtins.filter (service:
+ let srv = cfg.${service};
+ in srv.public && srv.enable
+ ) services;
+ in genAttrs publicServices' (service: {
+ getPublicAddressCmd = "cat ${config.nix-bitcoin.onionAddresses.dataDir}/${service}/${service}";
+ });
+ }
+ ];
+}
From 87fb9f246bd448d890e3958c4be786d81f264b27 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:18 +0100
Subject: [PATCH 18/32] add 'enable-tor' preset
Move 'enforceTor' and onion-service definitions from secure-node.nix.
Use the onionServices module to define onion services.
Onion services now automatically work for services that bind to an INADDR_ANY (`0.0.0.0`) address.
---
modules/onion-services.nix | 9 +++++
modules/presets/enable-tor.nix | 35 ++++++++++++++++++
modules/presets/secure-node.nix | 65 ++-------------------------------
3 files changed, 47 insertions(+), 62 deletions(-)
create mode 100644 modules/presets/enable-tor.nix
diff --git a/modules/onion-services.nix b/modules/onion-services.nix
index 7215543d3..755a4e784 100644
--- a/modules/onion-services.nix
+++ b/modules/onion-services.nix
@@ -99,5 +99,14 @@ in {
getPublicAddressCmd = "cat ${config.nix-bitcoin.onionAddresses.dataDir}/${service}/${service}";
});
}
+
+ # Set sensible defaults for some services
+ {
+ nix-bitcoin.onionServices = {
+ btcpayserver = {
+ externalPort = 80;
+ };
+ };
+ }
];
}
diff --git a/modules/presets/enable-tor.nix b/modules/presets/enable-tor.nix
new file mode 100644
index 000000000..41c50d208
--- /dev/null
+++ b/modules/presets/enable-tor.nix
@@ -0,0 +1,35 @@
+{ lib, ... }:
+let
+ defaultTrue = lib.mkDefault true;
+in {
+ services.tor = {
+ enable = true;
+ client.enable = true;
+ };
+
+ # Use Tor for all outgoing connections
+ services = {
+ bitcoind.enforceTor = true;
+ clightning.enforceTor = true;
+ lnd.enforceTor = true;
+ lightning-loop.enforceTor = true;
+ liquidd.enforceTor = true;
+ electrs.enforceTor = true;
+ # disable Tor enforcement until btcpayserver can fetch rates over Tor
+ # btcpayserver.enforceTor = true;
+ nbxplorer.enforceTor = true;
+ spark-wallet.enforceTor = true;
+ recurring-donations.enforceTor = true;
+ nix-bitcoin-webindex.enforceTor = true;
+ };
+
+ # Add onion services for incoming connections
+ nix-bitcoin.onionServices = {
+ bitcoind.enable = defaultTrue;
+ clightning.enable = defaultTrue;
+ lnd.enable = defaultTrue;
+ liquidd.enable = defaultTrue;
+ electrs.enable = defaultTrue;
+ btcpayserver.enable = defaultTrue;
+ };
+}
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 570c6c025..643a25af5 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -16,21 +16,9 @@ in {
../modules.nix
../nodeinfo.nix
../nix-bitcoin-webindex.nix
+ ./enable-tor.nix
];
- options = {
- services.clightning.onionport = mkOption {
- type = types.port;
- default = 9735;
- description = "Port on which to listen for tor client connections.";
- };
- services.lnd.onionport = mkOption {
- type = types.ints.u16;
- default = 9735;
- description = "Port on which to listen for tor client connections.";
- };
- };
-
config = {
# For backwards compatibility only
nix-bitcoin.secretsDir = mkDefault "/secrets";
@@ -39,20 +27,14 @@ in {
nix-bitcoin.security.hideProcessInformation = true;
- # Tor
- services.tor = {
- enable = true;
- client.enable = true;
-
- hiddenServices.sshd = mkHiddenService { port = 22; };
- };
+ services.tor.hiddenServices.sshd = mkHiddenService { port = 22; };
+ nix-bitcoin.onionAddresses.access.${operatorName} = [ "sshd" ];
# bitcoind
services.bitcoind = {
enable = true;
listen = true;
dataDirReadableByGroup = mkIf cfg.electrs.high-memory true;
- enforceTor = true;
assumevalid = "00000000000000000000e5abc3a74fe27dc0ead9c70ea1deb456f11c15fd7bc6";
addnodes = [ "ecoc5q34tmbq54wl.onion" ];
discover = false;
@@ -62,22 +44,6 @@ in {
# under high bitcoind rpc load
rpc.threads = 16;
};
- services.tor.hiddenServices.bitcoind = mkHiddenService { port = cfg.bitcoind.port; toHost = cfg.bitcoind.address; };
-
- # clightning
- services.clightning.enforceTor = true;
- services.tor.hiddenServices.clightning = mkIf cfg.clightning.enable (mkHiddenService {
- port = cfg.clightning.onionport;
- toHost = cfg.clightning.address;
- toPort = cfg.clightning.port;
- });
-
- # lnd
- services.lnd.enforceTor = true;
- services.tor.hiddenServices.lnd = mkIf cfg.lnd.enable (mkHiddenService { port = cfg.lnd.onionport; toHost = cfg.lnd.address; toPort = cfg.lnd.port; });
-
- # lightning-loop
- services.lightning-loop.enforceTor = true;
# liquidd
services.liquidd = {
@@ -85,33 +51,12 @@ in {
prune = 1000;
validatepegin = true;
listen = true;
- enforceTor = true;
- };
- services.tor.hiddenServices.liquidd = mkIf cfg.liquidd.enable (mkHiddenService { port = cfg.liquidd.port; toHost = cfg.liquidd.address; });
-
- # electrs
- services.electrs = {
- enforceTor = true;
};
- services.tor.hiddenServices.electrs = mkIf cfg.electrs.enable (mkHiddenService {
- port = cfg.electrs.port; toHost = cfg.electrs.address;
- });
-
- # btcpayserver
- # disable tor enforcement until btcpayserver can fetch rates over Tor
- services.btcpayserver.enforceTor = false;
- services.nbxplorer.enforceTor = true;
- services.tor.hiddenServices.btcpayserver = mkIf cfg.btcpayserver.enable (mkHiddenService { port = 80; toPort = 23000; toHost = cfg.btcpayserver.address; });
services.spark-wallet = {
onion-service = true;
- enforceTor = true;
};
- services.recurring-donations.enforceTor = true;
-
- services.nix-bitcoin-webindex.enforceTor = true;
-
# Backups
services.backups = {
program = "duplicity";
@@ -124,10 +69,6 @@ in {
qrencode
];
- nix-bitcoin.onionAddresses = {
- access.${operatorName} = [ "bitcoind" "clightning" "nginx" "liquidd" "spark-wallet" "electrs" "btcpayserver" "sshd" ];
- };
-
nix-bitcoin.operator.enable = true;
users.users.${operatorName} = {
openssh.authorizedKeys.keys = config.users.users.root.openssh.authorizedKeys.keys;
From bd2a46cb73de511b763d87593aadf6d0d9eefe11 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:19 +0100
Subject: [PATCH 19/32] spark-wallet: use onionServices
Also remove the unneeded definition of ReadWritePaths because the
service doesn't need write access to onion files.
---
modules/onion-services.nix | 9 +++++++++
modules/presets/enable-tor.nix | 1 +
modules/presets/secure-node.nix | 4 ----
modules/spark-wallet.nix | 35 +++++++++++++--------------------
4 files changed, 24 insertions(+), 25 deletions(-)
diff --git a/modules/onion-services.nix b/modules/onion-services.nix
index 755a4e784..db0dac173 100644
--- a/modules/onion-services.nix
+++ b/modules/onion-services.nix
@@ -103,6 +103,15 @@ in {
# Set sensible defaults for some services
{
nix-bitcoin.onionServices = {
+ spark-wallet = {
+ externalPort = 80;
+ # Enable 'public' by default, but don't auto-enable the onion service.
+ # When the onion service is enabled, 'public' lets spark-wallet generate
+ # a QR code for accessing the web interface.
+ public = true;
+ # Low priority so we can override this with mkDefault in ./presets/enable-tor.nix
+ enable = mkOverride 1400 false;
+ };
btcpayserver = {
externalPort = 80;
};
diff --git a/modules/presets/enable-tor.nix b/modules/presets/enable-tor.nix
index 41c50d208..2d5ffd3a5 100644
--- a/modules/presets/enable-tor.nix
+++ b/modules/presets/enable-tor.nix
@@ -31,5 +31,6 @@ in {
liquidd.enable = defaultTrue;
electrs.enable = defaultTrue;
btcpayserver.enable = defaultTrue;
+ spark-wallet.enable = defaultTrue;
};
}
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 643a25af5..5c6ee2313 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -53,10 +53,6 @@ in {
listen = true;
};
- services.spark-wallet = {
- onion-service = true;
- };
-
# Backups
services.backups = {
program = "duplicity";
diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix
index 52bcee1bd..a130dd2f4 100644
--- a/modules/spark-wallet.nix
+++ b/modules/spark-wallet.nix
@@ -5,14 +5,13 @@ with lib;
let
cfg = config.services.spark-wallet;
inherit (config) nix-bitcoin-services;
- onionAddressesService = (if cfg.onion-service then [ "onion-addresses.service" ] else []);
# Use wasabi rate provider because the default (bitstamp) doesn't accept
# connections through Tor
torRateProvider = "--rate-provider wasabi --proxy socks5h://${config.services.tor.client.socksListenAddress}";
startScript = ''
- ${optionalString cfg.onion-service ''
- publicURL="--public-url http://$(cat /var/lib/onion-addresses/spark-wallet/spark-wallet)"
+ ${optionalString (cfg.getPublicAddressCmd != "") ''
+ publicURL="--public-url http://$(${cfg.getPublicAddressCmd})"
''}
exec ${config.nix-bitcoin.pkgs.spark-wallet}/bin/spark-wallet \
--ln-path '${config.services.clightning.networkDir}' \
@@ -41,19 +40,21 @@ in {
default = 9737;
description = "http(s) server port.";
};
- onion-service = mkOption {
- type = types.bool;
- default = false;
- description = ''
- "If enabled, configures spark-wallet to be reachable through an onion service.";
- '';
- };
extraArgs = mkOption {
type = types.separatedString " ";
default = "";
description = "Extra command line arguments passed to spark-wallet.";
};
- enforceTor = nix-bitcoin-services.enforceTor;
+ getPublicAddressCmd = mkOption {
+ type = types.str;
+ default = "";
+ description = ''
+ Bash expression which outputs the public service address.
+ If set, spark-wallet prints a QR code to the systemd journal which
+ encodes an URL for accessing the web interface.
+ '';
+ };
+ inherit (nix-bitcoin-services) enforceTor;
};
config = mkIf cfg.enable {
@@ -66,24 +67,16 @@ in {
};
users.groups.spark-wallet = {};
- services.tor.hiddenServices.spark-wallet = mkIf cfg.onion-service {
- map = [{
- port = 80; toPort = cfg.port; toHost = cfg.address;
- }];
- version = 3;
- };
- nix-bitcoin.onionAddresses.access.spark-wallet = if cfg.onion-service then [ "spark-wallet" ] else [];
systemd.services.spark-wallet = {
description = "Run spark-wallet";
wantedBy = [ "multi-user.target" ];
- requires = [ "clightning.service" ] ++ onionAddressesService;
- after = [ "clightning.service" ] ++ onionAddressesService;
+ requires = [ "clightning.service" ];
+ after = [ "clightning.service" ];
script = startScript;
serviceConfig = nix-bitcoin-services.defaultHardening // {
User = "spark-wallet";
Restart = "on-failure";
RestartSec = "10s";
- ReadWritePaths = mkIf cfg.onion-service "/var/lib/onion-addresses";
} // (if cfg.enforceTor
then nix-bitcoin-services.allowTor
else nix-bitcoin-services.allowAnyIP)
From 3980cd5a4191e96d8cf1a942b89149a8c034b31c Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:20 +0100
Subject: [PATCH 20/32] clightning: use onionServices for address announcing
---
examples/configuration.nix | 11 ++++++-----
modules/clightning.nix | 30 ++++++++++++++++++------------
2 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/examples/configuration.nix b/examples/configuration.nix
index c16e31e41..725978712 100644
--- a/examples/configuration.nix
+++ b/examples/configuration.nix
@@ -37,11 +37,12 @@
# Enable this module to use clightning, a Lightning Network implementation
# in C.
services.clightning.enable = true;
- # == TOR
- # Enable this option to announce our Tor Hidden Service. By default clightning
- # offers outgoing functionality, but doesn't announce the Tor Hidden Service
- # under which peers can reach us.
- # services.clightning.announce-tor = true;
+ #
+ # Set this to create an onion service by which clightning can accept incoming connections
+ # via Tor.
+ # The onion service is automatically announced to peers.
+ # nix-bitcoin.onionServices.clightning.public = true;
+ #
# == Plugins
# See ../docs/usage.md for the list of available plugins.
# services.clightning.plugins.prometheus.enable = true;
diff --git a/modules/clightning.nix b/modules/clightning.nix
index fa621c4c7..04af32bd7 100644
--- a/modules/clightning.nix
+++ b/modules/clightning.nix
@@ -6,7 +6,6 @@ let
cfg = config.services.clightning;
inherit (config) nix-bitcoin-services;
nbPkgs = config.nix-bitcoin.pkgs;
- onionAddressesService = (if cfg.announce-tor then [ "onion-addresses.service" ] else []);
network = config.services.bitcoind.makeNetworkName "bitcoin" "regtest";
configFile = pkgs.writeText "config" ''
network=${network}
@@ -51,11 +50,6 @@ in {
Always use the *proxy*, even to connect to normal IP addresses (you can still connect to Unix domain sockets manually). This also disables all DNS lookups, to avoid leaking information.
'';
};
- announce-tor = mkOption {
- type = types.bool;
- default = false;
- description = "Announce clightning Tor Hidden Service";
- };
dataDir = mkOption {
type = types.path;
default = "/var/lib/clightning";
@@ -89,7 +83,15 @@ in {
'';
description = "Binary to connect with the clightning instance.";
};
- enforceTor = nix-bitcoin-services.enforceTor;
+ getPublicAddressCmd = mkOption {
+ type = types.str;
+ default = "";
+ description = ''
+ Bash expression which outputs the public service address to announce to peers.
+ If left empty, no address is announced.
+ '';
+ };
+ inherit (nix-bitcoin-services) enforceTor;
};
config = mkIf cfg.enable {
@@ -108,21 +110,25 @@ in {
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
];
- nix-bitcoin.onionAddresses.access.clightning = if cfg.announce-tor then [ "clightning" ] else [];
systemd.services.clightning = {
description = "Run clightningd";
path = [ nbPkgs.bitcoind ];
wantedBy = [ "multi-user.target" ];
- requires = [ "bitcoind.service" ] ++ onionAddressesService;
- after = [ "bitcoind.service" ] ++ onionAddressesService;
+ requires = [ "bitcoind.service" ];
+ after = [ "bitcoind.service" ];
preStart = ''
cp ${configFile} ${cfg.dataDir}/config
chown -R '${cfg.user}:${cfg.group}' '${cfg.dataDir}'
# The RPC socket has to be removed otherwise we might have stale sockets
rm -f ${cfg.networkDir}/lightning-rpc
chmod 640 ${cfg.dataDir}/config
- echo "bitcoin-rpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-public)" >> '${cfg.dataDir}/config'
- ${optionalString cfg.announce-tor "echo announce-addr=$(cat /var/lib/onion-addresses/clightning/clightning) >> '${cfg.dataDir}/config'"}
+ {
+ echo "bitcoin-rpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-public)"
+ ${optionalString (cfg.getPublicAddressCmd != "") ''
+ echo "announce-addr=$(${cfg.getPublicAddressCmd})"
+ ''}
+ } >> '${cfg.dataDir}/config'
+
'';
serviceConfig = nix-bitcoin-services.defaultHardening // {
ExecStart = "${nbPkgs.clightning}/bin/lightningd --lightning-dir=${cfg.dataDir}";
From bed00fe937a1e7e6a2496ac29ee904e4440b073e Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:21 +0100
Subject: [PATCH 21/32] lnd: use onionServices for address announcing
---
examples/configuration.nix | 10 ++++++----
modules/lnd.nix | 29 +++++++++++++++++------------
2 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/examples/configuration.nix b/examples/configuration.nix
index 725978712..d3484ed13 100644
--- a/examples/configuration.nix
+++ b/examples/configuration.nix
@@ -53,10 +53,12 @@
# you must disable clightning or change the services.clightning.port or
# services.lnd.port to a port other than 9735.
# services.lnd.enable = true;
- # Enable this option to announce our Tor Hidden Service. By default lnd
- # offers outgoing functionality, but doesn't announce the Tor Hidden Service
- # under which peers can reach us.
- # services.lnd.announce-tor = true;
+ #
+ # Set this to create an onion service by which lnd can accept incoming connections
+ # via Tor.
+ # The onion service is automatically announced to peers.
+ # nix-bitcoin.onionServices.lnd.public = true;
+ #
## WARNING
# If you use lnd, you should manually backup your wallet mnemonic
# seed. This will allow you to recover on-chain funds. You can run the
diff --git a/modules/lnd.nix b/modules/lnd.nix
index 05fe9f6e8..5a8629078 100644
--- a/modules/lnd.nix
+++ b/modules/lnd.nix
@@ -9,7 +9,6 @@ let
bitcoind = config.services.bitcoind;
bitcoindRpcAddress = bitcoind.rpc.address;
- onionAddressesService = (if cfg.announce-tor then [ "onion-addresses.service" ] else []);
networkDir = "${cfg.dataDir}/chain/bitcoin/${bitcoind.network}";
configFile = pkgs.writeText "lnd.conf" ''
datadir=${cfg.dataDir}
@@ -92,11 +91,6 @@ in {
default = if cfg.enforceTor then config.services.tor.client.socksListenAddress else null;
description = "Set a socks proxy to use to connect to Tor nodes";
};
- announce-tor = mkOption {
- type = types.bool;
- default = false;
- description = "Announce LND Tor Hidden Service";
- };
macaroons = mkOption {
default = {};
type = with types; attrsOf (submodule {
@@ -142,7 +136,15 @@ in {
'';
description = "Binary to connect with the lnd instance.";
};
- enforceTor = nix-bitcoin-services.enforceTor;
+ getPublicAddressCmd = mkOption {
+ type = types.str;
+ default = "";
+ description = ''
+ Bash expression which outputs the public service address to announce to peers.
+ If left empty, no address is announced.
+ '';
+ };
+ inherit (nix-bitcoin-services) enforceTor;
};
config = mkIf cfg.enable {
@@ -165,16 +167,19 @@ in {
zmqpubrawtx = "tcp://${bitcoindRpcAddress}:28333";
};
- nix-bitcoin.onionAddresses.access.lnd = if cfg.announce-tor then [ "lnd" ] else [];
systemd.services.lnd = {
description = "Run LND";
wantedBy = [ "multi-user.target" ];
- requires = [ "bitcoind.service" ] ++ onionAddressesService;
- after = [ "bitcoind.service" ] ++ onionAddressesService;
+ requires = [ "bitcoind.service" ];
+ after = [ "bitcoind.service" ];
preStart = ''
install -m600 ${configFile} '${cfg.dataDir}/lnd.conf'
- echo "bitcoind.rpcpass=$(cat ${secretsDir}/bitcoin-rpcpassword-public)" >> '${cfg.dataDir}/lnd.conf'
- ${optionalString cfg.announce-tor "echo externalip=$(cat /var/lib/onion-addresses/lnd/lnd) >> '${cfg.dataDir}/lnd.conf'"}
+ {
+ echo "bitcoind.rpcpass=$(cat ${secretsDir}/bitcoin-rpcpassword-public)"
+ ${optionalString (cfg.getPublicAddressCmd != "") ''
+ echo "externalip=$(${cfg.getPublicAddressCmd})"
+ ''}
+ } >> '${cfg.dataDir}/lnd.conf'
'';
serviceConfig = nix-bitcoin-services.defaultHardening // {
RuntimeDirectory = "lnd"; # Only used to store custom macaroons
From 45c40c4eb94b1176216ca2b466442b8029ca8b51 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:22 +0100
Subject: [PATCH 22/32] versioning: simplify assertion evaluation
---
modules/versioning.nix | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/versioning.nix b/modules/versioning.nix
index ff447280e..f811779a0 100644
--- a/modules/versioning.nix
+++ b/modules/versioning.nix
@@ -93,6 +93,6 @@ in
config = {
# Force evaluation. An actual option value is never assigned
- system.extraDependencies = optional (builtins.length incompatibleChanges > 0) (builtins.throw errorMsg);
+ system = optionalAttrs (builtins.length incompatibleChanges > 0) (builtins.throw errorMsg);
};
}
From 18c7842e1affa87df63809cd2f7a6b068468918e Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:23 +0100
Subject: [PATCH 23/32] modules: show warnings for obsolete options
---
modules/obsolete-options.nix | 28 ++++++++++++++++++++++++++++
modules/versioning.nix | 4 ++++
2 files changed, 32 insertions(+)
create mode 100644 modules/obsolete-options.nix
diff --git a/modules/obsolete-options.nix b/modules/obsolete-options.nix
new file mode 100644
index 000000000..4c39affc7
--- /dev/null
+++ b/modules/obsolete-options.nix
@@ -0,0 +1,28 @@
+{ lib, ... }:
+
+with lib;
+let
+ mkRenamedAnnounceTorOption = service:
+ # use mkRemovedOptionModule because mkRenamedOptionModule fails with an infinite recursion error
+ mkRemovedOptionModule [ "services" service "announce-tor" ] ''
+ Use option `nix-bitcoin.onionServices.${service}.public` instead.
+ '';
+in {
+ imports = [
+ (mkRenamedOptionModule [ "services" "bitcoind" "bind" ] [ "services" "bitcoind" "address" ])
+ (mkRenamedOptionModule [ "services" "bitcoind" "rpcallowip" ] [ "services" "bitcoind" "rpc" "allowip" ])
+ (mkRenamedOptionModule [ "services" "bitcoind" "rpcthreads" ] [ "services" "bitcoind" "rpc" "threads" ])
+ (mkRenamedOptionModule [ "services" "clightning" "bind-addr" ] [ "services" "clightning" "address" ])
+ (mkRenamedOptionModule [ "services" "clightning" "bindport" ] [ "services" "clightning" "port" ])
+ (mkRenamedOptionModule [ "services" "spark-wallet" "host" ] [ "services" "spark-wallet" "address" ])
+ (mkRenamedOptionModule [ "services" "lnd" "rpclisten" ] [ "services" "lnd" "rpcAddress" ])
+ (mkRenamedOptionModule [ "services" "lnd" "listen" ] [ "services" "lnd" "address" ])
+ (mkRenamedOptionModule [ "services" "lnd" "listenPort" ] [ "services" "lnd" "port" ])
+ (mkRenamedOptionModule [ "services" "btcpayserver" "bind" ] [ "services" "btcpayserver" "address" ])
+ (mkRenamedOptionModule [ "services" "liquidd" "bind" ] [ "services" "liquidd" "address" ])
+ (mkRenamedOptionModule [ "services" "liquidd" "rpcbind" ] [ "services" "liquidd" "rpc" "address" ])
+
+ (mkRenamedAnnounceTorOption "clightning")
+ (mkRenamedAnnounceTorOption "lnd")
+ ];
+}
diff --git a/modules/versioning.nix b/modules/versioning.nix
index f811779a0..3803c862c 100644
--- a/modules/versioning.nix
+++ b/modules/versioning.nix
@@ -76,6 +76,10 @@ let
lastChange = builtins.elemAt changes (builtins.length changes - 1);
in
{
+ imports = [
+ ./obsolete-options.nix
+ ];
+
options = {
nix-bitcoin.configVersion = mkOption {
type = with types; nullOr str;
From 2a240d6f4a2bc624772b2065f07b1f1a55bf4eb0 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:24 +0100
Subject: [PATCH 24/32] enable-tor: disable default onion services for
clightning, lnd, btcpayserver
In case of btcpayserver the default onion service is a security risk
because any visitor can register an admin account on a freshly setup node.
---
README.md | 2 +-
examples/README.md | 2 +-
examples/configuration.nix | 8 +++++++-
modules/presets/enable-tor.nix | 3 ---
modules/versioning.nix | 17 ++++++++++++++++-
5 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 62d2970cd..8489d978f 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,7 @@ See the [examples directory](examples/README.md).
Features
---
A [configuration preset](modules/presets/secure-node.nix) for setting up a secure node
-* All applications use Tor for outbound connections and accept inbound connections via onion services.
+* All applications use Tor for outbound connections and support accepting inbound connections via onion services.
* Includes a [nodeinfo](modules/nodeinfo.nix) script which prints basic info about the node.
NixOS modules
diff --git a/examples/README.md b/examples/README.md
index 1280afbbc..328c6aac6 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -11,7 +11,7 @@ nix-shell
The following example scripts set up a nix-bitcoin node according to [`configuration.nix`](configuration.nix) and then
shut down immediately. They leave no traces (outside of `/nix/store`) on the host system.\
-By default, [`configuration.nix`](configuration.nix) enables `bitcoind` and `clightning` (with an onion service).
+By default, [`configuration.nix`](configuration.nix) enables `bitcoind` and `clightning`.
- [`./deploy-container.sh`](deploy-container.sh) creates a [NixOS container](https://github.com/erikarvstedt/extra-container).\
This is the fastest way to set up a node.\
diff --git a/examples/configuration.nix b/examples/configuration.nix
index d3484ed13..1d358dbbd 100644
--- a/examples/configuration.nix
+++ b/examples/configuration.nix
@@ -96,6 +96,12 @@
# The lightning backend service automatically enabled.
# Afterwards you need to go into Store > General Settings > Lightning Nodes
# and click to use "the internal lightning node of this BTCPay Server".
+ #
+ # Set this to create an onion service to make the btcpayserver web interface
+ # accessible via Tor.
+ # Security WARNING: Create a btcpayserver administrator account before allowing
+ # public access to the web interface.
+ # nix-bitcoin.onionServices.btcpayserver.enable = true;
### LIQUIDD
# Enable this module to use Liquid, a sidechain for an inter-exchange
@@ -206,5 +212,5 @@
# The nix-bitcoin release version that your config is compatible with.
# 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.26";
+ nix-bitcoin.configVersion = "0.0.30";
}
diff --git a/modules/presets/enable-tor.nix b/modules/presets/enable-tor.nix
index 2d5ffd3a5..cdbd4d619 100644
--- a/modules/presets/enable-tor.nix
+++ b/modules/presets/enable-tor.nix
@@ -26,11 +26,8 @@ in {
# Add onion services for incoming connections
nix-bitcoin.onionServices = {
bitcoind.enable = defaultTrue;
- clightning.enable = defaultTrue;
- lnd.enable = defaultTrue;
liquidd.enable = defaultTrue;
electrs.enable = defaultTrue;
- btcpayserver.enable = defaultTrue;
spark-wallet.enable = defaultTrue;
};
}
diff --git a/modules/versioning.nix b/modules/versioning.nix
index 3803c862c..f06a593d9 100644
--- a/modules/versioning.nix
+++ b/modules/versioning.nix
@@ -5,7 +5,19 @@ let
version = config.nix-bitcoin.configVersion;
# Sorted by increasing version numbers
- changes = [
+ changes = let
+ mkOnionServiceChange = service: {
+ version = "0.0.30";
+ condition = config.services.${service}.enable;
+ message = ''
+ The onion service for ${service} has been disabled in the default
+ configuration (`secure-node.nix`).
+
+ To enable the onion service, add the following to your configuration:
+ nix-bitcon.onionServices.${service}.enable = true;
+ '';
+ };
+ in [
{
version = "0.0.26";
condition = config.services.joinmarket.enable;
@@ -54,6 +66,9 @@ let
https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/v0.8.0/docs/NATIVE-SEGWIT-UPGRADE.md
'';
}
+ (mkOnionServiceChange "clightning")
+ (mkOnionServiceChange "lnd")
+ (mkOnionServiceChange "btcpayserver")
];
incompatibleChanges = optionals
From f6b883a9acd92e3d94062b21615db14c8383f3b7 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:25 +0100
Subject: [PATCH 25/32] remove webindex
This module is outdated and incomplete. We can readd an improved version in
the future.
Move nanopos nginx proxy tests to the nanopos test.
---
README.md | 1 -
docs/usage.md | 2 +-
examples/configuration.nix | 5 --
modules/default.nix | 1 -
modules/nix-bitcoin-webindex.nix | 105 -------------------------------
modules/presets/enable-tor.nix | 1 -
modules/presets/secure-node.nix | 1 -
test/tests.nix | 1 -
test/tests.py | 8 ---
9 files changed, 1 insertion(+), 124 deletions(-)
delete mode 100644 modules/nix-bitcoin-webindex.nix
diff --git a/README.md b/README.md
index 8489d978f..8ebba91de 100644
--- a/README.md
+++ b/README.md
@@ -76,7 +76,6 @@ NixOS modules
* [netns-isolation](modules/netns-isolation.nix): isolates applications on the network-level via network namespaces
* [backups](modules/backups.nix): daily duplicity backups of all your node's important files
* [operator](modules/operator.nix): adds non-root user `operator` who has access to client tools (e.g. `bitcoin-cli`, `lightning-cli`)
- * [nix-bitcoin webindex](modules/nix-bitcoin-webindex.nix): a local website to display node information
Security
---
diff --git a/docs/usage.md b/docs/usage.md
index 53d1c8b2b..d6baab404 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -8,7 +8,7 @@ fetch-release > nix-bitcoin-release.nix
Nodeinfo
---
-Run `nodeinfo` to see your onion addresses for the webindex, spark, etc. if they are enabled.
+Run `nodeinfo` to see the onion addresses for enabled services.
Connect to spark-wallet
---
diff --git a/examples/configuration.nix b/examples/configuration.nix
index 1d358dbbd..8ebd0370a 100644
--- a/examples/configuration.nix
+++ b/examples/configuration.nix
@@ -110,11 +110,6 @@
# tool run as user operator.
# services.liquidd.enable = true;
- ### WEBINDEX
- # Enable this module to use the nix-bitcoin-webindex, a simple website
- # displaying your node information. Only available if clightning is enabled.
- # services.nix-bitcoin-webindex.enable = true;
-
### RECURRING-DONATIONS
# Enable this module to send recurring donations. This is EXPERIMENTAL; it's
# not guaranteed that payments are succeeding or that you will notice payment
diff --git a/modules/default.nix b/modules/default.nix
index 72d766150..cc013a5d5 100644
--- a/modules/default.nix
+++ b/modules/default.nix
@@ -6,7 +6,6 @@
electrs = ./electrs.nix;
liquid = ./liquid.nix;
presets.secure-node = ./presets/secure-node.nix;
- nix-bitcoin-webindex = ./nix-bitcoin-webindex.nix;
spark-wallet = ./spark-wallet.nix;
recurring-donations = ./recurring-donations.nix;
lnd = ./lnd.nix;
diff --git a/modules/nix-bitcoin-webindex.nix b/modules/nix-bitcoin-webindex.nix
deleted file mode 100644
index 4224243cb..000000000
--- a/modules/nix-bitcoin-webindex.nix
+++ /dev/null
@@ -1,105 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
- cfg = config.services.nix-bitcoin-webindex;
- inherit (config) nix-bitcoin-services;
- indexFile = pkgs.writeText "index.html" ''
-
-
-
-
- nix-bitcoin
-
-
-
-
- lightning node: CLIGHTNING_ID
-
-
-
-
- '';
- createWebIndex = pkgs.writeText "make-index.sh" ''
- set -e
- cp ${indexFile} /var/www/index.html
- chown -R nginx:nginx /var/www/
- nodeinfo
- . <(nodeinfo)
- sed -i "s/CLIGHTNING_ID/$CLIGHTNING_ID/g" /var/www/index.html
- '';
-in {
- options.services.nix-bitcoin-webindex = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description = ''
- If enabled, the webindex service will be installed.
- '';
- };
- host = mkOption {
- type = types.str;
- default = if config.nix-bitcoin.netns-isolation.enable then
- config.nix-bitcoin.netns-isolation.netns.nginx.address
- else
- "localhost";
- description = "HTTP server listen address.";
- };
- enforceTor = nix-bitcoin-services.enforceTor;
- };
-
- config = mkIf cfg.enable {
- assertions = [
- { assertion = config.services.clightning.enable;
- message = "nix-bitcoin-webindex requires clightning.";
- }
- ];
-
- systemd.tmpfiles.rules = [
- "d /var/www 0755 nginx nginx - -"
- ];
-
- services.nginx = {
- enable = true;
- virtualHosts."_" = {
- root = "/var/www";
- };
- };
- services.tor.hiddenServices.nginx = {
- map = [{
- port = 80; toHost = cfg.host;
- } {
- port = 443; toHost = cfg.host;
- }];
- version = 3;
- };
-
- # create-web-index
- systemd.services.create-web-index = {
- description = "Get node info";
- wantedBy = [ "multi-user.target" ];
- path = with pkgs; [
- config.programs.nodeinfo
- jq
- sudo
- ] ++ optional config.services.lnd.enable config.services.lnd.cli
- ++ optional config.services.clightning.enable config.services.clightning.cli;
- serviceConfig = nix-bitcoin-services.defaultHardening // {
- ExecStart="${pkgs.bash}/bin/bash ${createWebIndex}";
- User = "root";
- Type = "simple";
- RemainAfterExit="yes";
- Restart = "on-failure";
- RestartSec = "10s";
- PrivateNetwork = "true"; # This service needs no network access
- PrivateUsers = "false";
- ReadWritePaths = "/var/www";
- CapabilityBoundingSet = "CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_SYS_ADMIN CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_IPC_OWNER";
- } // (if cfg.enforceTor
- then nix-bitcoin-services.allowTor
- else nix-bitcoin-services.allowAnyIP
- );
- };
- };
-}
diff --git a/modules/presets/enable-tor.nix b/modules/presets/enable-tor.nix
index cdbd4d619..8d16a9e35 100644
--- a/modules/presets/enable-tor.nix
+++ b/modules/presets/enable-tor.nix
@@ -20,7 +20,6 @@ in {
nbxplorer.enforceTor = true;
spark-wallet.enforceTor = true;
recurring-donations.enforceTor = true;
- nix-bitcoin-webindex.enforceTor = true;
};
# Add onion services for incoming connections
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 5c6ee2313..1f1d01242 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -15,7 +15,6 @@ in {
imports = [
../modules.nix
../nodeinfo.nix
- ../nix-bitcoin-webindex.nix
./enable-tor.nix
];
diff --git a/test/tests.nix b/test/tests.nix
index 758e9b657..98b12ff72 100644
--- a/test/tests.nix
+++ b/test/tests.nix
@@ -130,7 +130,6 @@ let testEnv = rec {
scenarios.full
../modules/presets/secure-node.nix
];
- services.nix-bitcoin-webindex.enable = true;
tests.secure-node = true;
tests.banlist-and-restart = true;
diff --git a/test/tests.py b/test/tests.py
index 18afd1eff..01b27e551 100644
--- a/test/tests.py
+++ b/test/tests.py
@@ -220,14 +220,6 @@ def _():
def _():
assert_running("onion-addresses")
- # FIXME: use 'wait_for_unit' because 'create-web-index' always fails during startup due
- # to incomplete unit dependencies.
- # 'create-web-index' implicitly tests 'nodeinfo'.
- machine.wait_for_unit("create-web-index")
- assert_running("nginx")
- wait_for_open_port(ip("nginx"), 80)
- assert_matches(f"curl {ip('nginx')}", "nix-bitcoin")
-
# Run this test before the following tests that shut down services
# (and their corresponding network namespaces).
From 323a431abade32e3c5f0f98acfaada6a80edc1d0 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:26 +0100
Subject: [PATCH 26/32] improve nodeinfo
- enable usage outside of secure-node.nix
- use json as the output format
- show ports
- also show local addresses, which is particularly useful when
netns-isolation is enabled
- only show enabled services
---
README.md | 2 +-
docs/usage.md | 28 +++---
modules/modules.nix | 1 +
modules/nodeinfo.nix | 163 ++++++++++++++++++++------------
modules/presets/secure-node.nix | 3 +-
test/tests.nix | 4 +
test/tests.py | 10 ++
7 files changed, 135 insertions(+), 76 deletions(-)
diff --git a/README.md b/README.md
index 8ebba91de..2f5d5f94c 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,6 @@ 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.
-* Includes a [nodeinfo](modules/nodeinfo.nix) script which prints basic info about the node.
NixOS modules
* Application services
@@ -74,6 +73,7 @@ NixOS modules
* [bitcoin-core-hwi](https://github.com/bitcoin-core/HWI)
* Helper
* [netns-isolation](modules/netns-isolation.nix): isolates applications on the network-level via network namespaces
+ * [nodeinfo](modules/nodeinfo.nix): script which prints info about the node's services
* [backups](modules/backups.nix): daily duplicity backups of all your node's important files
* [operator](modules/operator.nix): adds non-root user `operator` who has access to client tools (e.g. `bitcoin-cli`, `lightning-cli`)
diff --git a/docs/usage.md b/docs/usage.md
index d6baab404..5d3985d4a 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -8,7 +8,7 @@ fetch-release > nix-bitcoin-release.nix
Nodeinfo
---
-Run `nodeinfo` to see the onion addresses for enabled services.
+Run `nodeinfo` to see onion addresses and local addresses for enabled services.
Connect to spark-wallet
---
@@ -86,10 +86,10 @@ Connect to electrs
nixops deploy -d bitcoin-node
```
-3. Get electrs onion address
+3. Get electrs onion address with format `:`
```
- nodeinfo | grep 'ELECTRS_ONION'
+ nodeinfo | jq -r .electrs.onion_address
```
4. Connect to electrs
@@ -98,7 +98,7 @@ Connect to electrs
On Desktop
```
- electrum --oneserver -1 -s ":50001:t" -p socks5:localhost:9050
+ electrum --oneserver -1 -s ":t" -p socks5:localhost:9050
```
On Android
@@ -107,16 +107,16 @@ Connect to electrs
Network > Proxy mode: socks5, Host: 127.0.0.1, Port: 9050
Network > Auto-connect: OFF
Network > One-server mode: ON
- Network > Server: :50001:t
+ Network > Server: :t
```
-Connect to nix-bitcoin node through ssh Tor Hidden Service
+Connect to nix-bitcoin node through the SSH onion service
---
-1. Run `nodeinfo` on your nix-bitcoin node and note the `SSHD_ONION`
+1. Get the SSH onion address (excluding the port suffix)
```
nixops ssh operator@bitcoin-node
- nodeinfo | grep 'SSHD_ONION'
+ nodeinfo | jq -r .sshd.onion_address | sed 's/:.*//'
```
2. Create a SSH key
@@ -131,14 +131,14 @@ Connect to nix-bitcoin node through ssh Tor Hidden Service
# FIXME: Add your SSH pubkey
services.openssh.enable = true;
users.users.root = {
- openssh.authorizedKeys.keys = [ "[contents of ~/.ssh/id_ed25519.pub]" ];
+ openssh.authorizedKeys.keys = [ "" ];
};
```
-4. Connect to your nix-bitcoin node's ssh Tor Hidden Service, forwarding a local port to the nix-bitcoin node's ssh server
+4. Connect to your nix-bitcoin node's SSH onion service, forwarding a local port to the nix-bitcoin node's SSH server
```
- ssh -i ~/.ssh/id_ed25519 -L [random port of your choosing]:localhost:22 root@[your SSHD_ONION]
+ ssh -i ~/.ssh/id_ed25519 -L :localhost:22 root@
```
5. Edit your `network-nixos.nix` to look like this
@@ -148,12 +148,12 @@ Connect to nix-bitcoin node through ssh Tor Hidden Service
bitcoin-node =
{ config, pkgs, ... }:
{ deployment.targetHost = "127.0.0.1";
- deployment.targetPort = [random port of your choosing];
+ deployment.targetPort = ;
};
}
```
-6. Now you can run `nixops deploy -d bitcoin-node` and it will connect through the ssh tunnel you established in step iv. This also allows you to do more complex ssh setups that `nixops ssh` doesn't support. An example would be authenticating with [Trezor's ssh agent](https://github.com/romanz/trezor-agent), which provides extra security.
+6. Now you can run `nixops deploy -d bitcoin-node` and it will connect through the SSH tunnel you established in step iv. This also allows you to do more complex SSH setups that `nixops ssh` doesn't support. An example would be authenticating with [Trezor's SSH agent](https://github.com/romanz/trezor-agent), which provides extra security.
Initialize a Trezor for Bitcoin Core's Hardware Wallet Interface
---
@@ -263,7 +263,7 @@ you. If however, you want to manually initialize your wallet, follow these steps
## Run the tumbler
The tumbler needs to be able to run in the background for a long time, use screen
-to run it accross ssh sessions. You can also use tmux in the same fashion.
+to run it accross SSH sessions. You can also use tmux in the same fashion.
1. Add screen to your `environment.systemPackages`, for example
diff --git a/modules/modules.nix b/modules/modules.nix
index d2e669075..4788da6ef 100644
--- a/modules/modules.nix
+++ b/modules/modules.nix
@@ -27,6 +27,7 @@ with lib;
./onion-addresses.nix
./onion-services.nix
./netns-isolation.nix
+ ./nodeinfo.nix
./backups.nix
];
diff --git a/modules/nodeinfo.nix b/modules/nodeinfo.nix
index 254ad0609..afd3fa67c 100644
--- a/modules/nodeinfo.nix
+++ b/modules/nodeinfo.nix
@@ -1,74 +1,117 @@
{ config, lib, pkgs, ... }:
with lib;
-
let
- operatorName = config.nix-bitcoin.operator.name;
+ cfg = config.nix-bitcoin.nodeinfo;
+
+ # Services included in the output
+ services = {
+ bitcoind = mkInfo "";
+ clightning = mkInfo ''
+ info["nodeid"] = shell("lightning-cli getinfo | jq -r '.id'")
+ if 'onion_address' in info:
+ info["id"] = f"{info['nodeid']}@{info['onion_address']}"
+ '';
+ lnd = mkInfo ''
+ info["nodeid"] = shell("lightning-cli getinfo | jq -r '.id'")
+ '';
+ electrs = mkInfo "";
+ spark-wallet = mkInfo "";
+ btcpayserver = mkInfo "";
+ liquidd = mkInfo "";
+ # Only add sshd when it has an onion service
+ sshd = name: cfg: mkIfOnionPort "sshd" (onionPort: ''
+ add_service("sshd", """set_onion_address(info, "sshd", ${onionPort})""")
+ '');
+ };
+
script = pkgs.writeScriptBin "nodeinfo" ''
- set -eo pipefail
-
- BITCOIND_ONION="$(cat /var/lib/onion-addresses/${operatorName}/bitcoind)"
- echo BITCOIND_ONION="$BITCOIND_ONION"
-
- if systemctl is-active --quiet clightning; then
- CLIGHTNING_NODEID=$(lightning-cli getinfo | jq -r '.id')
- CLIGHTNING_ONION="$(cat /var/lib/onion-addresses/${operatorName}/clightning)"
- CLIGHTNING_ID="$CLIGHTNING_NODEID@$CLIGHTNING_ONION:9735"
- echo CLIGHTNING_NODEID="$CLIGHTNING_NODEID"
- echo CLIGHTNING_ONION="$CLIGHTNING_ONION"
- echo CLIGHTNING_ID="$CLIGHTNING_ID"
- fi
-
- if systemctl is-active --quiet lnd; then
- LND_NODEID=$(lncli getinfo | jq -r '.uris[0]')
- echo LND_NODEID="$LND_NODEID"
- fi
-
- NGINX_ONION_FILE=/var/lib/onion-addresses/${operatorName}/nginx
- if [ -e "$NGINX_ONION_FILE" ]; then
- NGINX_ONION="$(cat $NGINX_ONION_FILE)"
- echo NGINX_ONION="$NGINX_ONION"
- fi
-
- LIQUIDD_ONION_FILE=/var/lib/onion-addresses/${operatorName}/liquidd
- if [ -e "$LIQUIDD_ONION_FILE" ]; then
- LIQUIDD_ONION="$(cat $LIQUIDD_ONION_FILE)"
- echo LIQUIDD_ONION="$LIQUIDD_ONION"
- fi
-
- SPARKWALLET_ONION_FILE=/var/lib/onion-addresses/${operatorName}/spark-wallet
- if [ -e "$SPARKWALLET_ONION_FILE" ]; then
- SPARKWALLET_ONION="$(cat $SPARKWALLET_ONION_FILE)"
- echo SPARKWALLET_ONION="http://$SPARKWALLET_ONION"
- fi
-
- ELECTRS_ONION_FILE=/var/lib/onion-addresses/${operatorName}/electrs
- if [ -e "$ELECTRS_ONION_FILE" ]; then
- ELECTRS_ONION="$(cat $ELECTRS_ONION_FILE)"
- echo ELECTRS_ONION="$ELECTRS_ONION"
- fi
-
- BTCPAYSERVER_ONION_FILE=/var/lib/onion-addresses/${operatorName}/btcpayserver
- if [ -e "$BTCPAYSERVER_ONION_FILE" ]; then
- BTCPAYSERVER_ONION="$(cat $BTCPAYSERVER_ONION_FILE)"
- echo BTCPAYSERVER_ONION="$BTCPAYSERVER_ONION"
- fi
-
- SSHD_ONION_FILE=/var/lib/onion-addresses/${operatorName}/sshd
- if [ -e "$SSHD_ONION_FILE" ]; then
- SSHD_ONION="$(cat $SSHD_ONION_FILE)"
- echo SSHD_ONION="$SSHD_ONION"
- fi
+ #!${pkgs.python3}/bin/python
+
+ import json
+ import subprocess
+ from collections import OrderedDict
+
+ def success(*args):
+ return subprocess.call(args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0
+
+ def is_active(unit):
+ return success("systemctl", "is-active", "--quiet", unit)
+
+ def is_enabled(unit):
+ return success("systemctl", "is-enabled", "--quiet", unit)
+
+ def cmd(*args):
+ return subprocess.run(args, stdout=subprocess.PIPE).stdout.decode('utf-8')
+
+ def shell(*args):
+ return cmd("bash", "-c", *args).strip()
+
+ infos = OrderedDict()
+ operator = "${config.nix-bitcoin.operator.name}"
+
+ def set_onion_address(info, name, port):
+ path = f"/var/lib/onion-addresses/{operator}/{name}"
+ try:
+ with open(path, "r") as f:
+ onion_address = f.read().strip()
+ except OSError:
+ print(f"error reading file {path}", file=sys.stderr)
+ return
+ info["onion_address"] = f"{onion_address}:{port}"
+
+ def add_service(service, make_info):
+ if not is_active(service):
+ infos[service] = "service is not running"
+ else:
+ info = OrderedDict()
+ exec(make_info, globals(), locals())
+ infos[service] = info
+
+ if is_enabled("onion-adresses") and not is_active("onion-adresses"):
+ print("error: service 'onion-adresses' is not running")
+ exit(1)
+
+ ${concatStrings infos}
+
+ print(json.dumps(infos, indent=2))
'';
+
+ infos = map (service:
+ let cfg = config.services.${service};
+ in optionalString cfg.enable (services.${service} service cfg)
+ ) (builtins.attrNames services);
+
+ mkInfo = extraCode: name: cfg:
+ ''
+ add_service("${name}", """
+ info["local_address"] = "${cfg.address}:${toString cfg.port}"
+ '' + mkIfOnionPort name (onionPort: ''
+ set_onion_address(info, "${name}", ${onionPort})
+ '') + extraCode + ''
+
+ """)
+ '';
+
+ mkIfOnionPort = name: fn:
+ if hiddenServices ? ${name} then
+ fn (toString (builtins.elemAt hiddenServices.${name}.map 0).port)
+ else
+ "";
+
+ inherit (config.services.tor) hiddenServices;
in {
options = {
- programs.nodeinfo = mkOption {
- readOnly = true;
- default = script;
+ nix-bitcoin.nodeinfo = {
+ enable = mkEnableOption "nodeinfo";
+ program = mkOption {
+ readOnly = true;
+ default = script;
+ };
};
};
config = {
- environment.systemPackages = [ script ];
+ environment.systemPackages = optional cfg.enable script;
};
}
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 1f1d01242..335c3646e 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -14,7 +14,6 @@ let
in {
imports = [
../modules.nix
- ../nodeinfo.nix
./enable-tor.nix
];
@@ -75,5 +74,7 @@ in {
cp "${config.users.users.root.home}/.vbox-nixops-client-key" "${config.users.users.${operatorName}.home}"
'';
};
+
+ nix-bitcoin.nodeinfo.enable = true;
};
}
diff --git a/test/tests.nix b/test/tests.nix
index 98b12ff72..83e462961 100644
--- a/test/tests.nix
+++ b/test/tests.nix
@@ -68,6 +68,8 @@ let testEnv = rec {
'';
};
+ tests.nodeinfo = config.nix-bitcoin.nodeinfo.enable;
+
tests.backups = cfg.backups.enable;
# To test that unused secrets are made inaccessible by 'setup-secrets'
@@ -119,6 +121,8 @@ let testEnv = rec {
services.joinmarket.enable = true;
services.backups.enable = true;
+ nix-bitcoin.nodeinfo.enable = true;
+
services.hardware-wallets = {
trezor = true;
ledger = true;
diff --git a/test/tests.py b/test/tests.py
index 01b27e551..329dcc6f8 100644
--- a/test/tests.py
+++ b/test/tests.py
@@ -216,6 +216,16 @@ def _():
)
+@test("nodeinfo")
+def _():
+ status, _ = machine.execute("systemctl is-enabled --quiet onion-addresses 2> /dev/null")
+ if status == 0:
+ machine.wait_for_unit("onion-addresses")
+ json_info = succeed("sudo -u operator nodeinfo")
+ info = json.loads(json_info)
+ assert info["bitcoind"]["local_address"]
+
+
@test("secure-node")
def _():
assert_running("onion-addresses")
From 04d8560f86e94fc9d2f9df1c8334e11442b75373 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:27 +0100
Subject: [PATCH 27/32] secure-node: remove qrencode, tor from systemPackages
Keep jq which is useful for analyzing service cli output.
---
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 335c3646e..6c9e485ff 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -58,9 +58,7 @@ in {
};
environment.systemPackages = with pkgs; [
- tor
jq
- qrencode
];
nix-bitcoin.operator.enable = true;
From 5f7a7962f77057dba76954bb44813006b98cecde Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:28 +0100
Subject: [PATCH 28/32] backups: remove redundant option 'program'
Not needed until we support other backup backends.
---
modules/backups.nix | 9 +--------
modules/presets/secure-node.nix | 5 +----
2 files changed, 2 insertions(+), 12 deletions(-)
diff --git a/modules/backups.nix b/modules/backups.nix
index 7060980af..322a84c6d 100644
--- a/modules/backups.nix
+++ b/modules/backups.nix
@@ -31,13 +31,6 @@ let
in {
options.services.backups = {
enable = mkEnableOption "Backups service";
- program = mkOption {
- type = types.enum [ "duplicity" ];
- default = "duplicity";
- description = ''
- Program with which to do backups.
- '';
- };
with-bulk-data = mkOption {
type = types.bool;
default = false;
@@ -69,7 +62,7 @@ in {
};
};
- config = mkIf (cfg.enable && cfg.program == "duplicity") (mkMerge [
+ config = mkIf cfg.enable (mkMerge [
{
environment.systemPackages = [ pkgs.duplicity ];
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 6c9e485ff..e8ab5afd8 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -52,10 +52,7 @@ in {
};
# Backups
- services.backups = {
- program = "duplicity";
- frequency = "daily";
- };
+ services.backups.frequency = "daily";
environment.systemPackages = with pkgs; [
jq
From 0e00c39d4784bc64e30b1fc37c684e75e08bdaa6 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:29 +0100
Subject: [PATCH 29/32] secure-node: improve layout
---
modules/presets/secure-node.nix | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index e8ab5afd8..0b1e4b637 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -25,10 +25,14 @@ in {
nix-bitcoin.security.hideProcessInformation = true;
+ environment.systemPackages = with pkgs; [
+ jq
+ ];
+
+ # sshd
services.tor.hiddenServices.sshd = mkHiddenService { port = 22; };
nix-bitcoin.onionAddresses.access.${operatorName} = [ "sshd" ];
- # bitcoind
services.bitcoind = {
enable = true;
listen = true;
@@ -43,7 +47,6 @@ in {
rpc.threads = 16;
};
- # liquidd
services.liquidd = {
rpcuser = "liquidrpc";
prune = 1000;
@@ -51,13 +54,11 @@ in {
listen = true;
};
- # Backups
- services.backups.frequency = "daily";
+ nix-bitcoin.nodeinfo.enable = true;
- environment.systemPackages = with pkgs; [
- jq
- ];
+ services.backups.frequency = "daily";
+ # operator
nix-bitcoin.operator.enable = true;
users.users.${operatorName} = {
openssh.authorizedKeys.keys = config.users.users.root.openssh.authorizedKeys.keys;
@@ -69,7 +70,5 @@ in {
cp "${config.users.users.root.home}/.vbox-nixops-client-key" "${config.users.users.${operatorName}.home}"
'';
};
-
- nix-bitcoin.nodeinfo.enable = true;
};
}
From 757a66b9bd1784d9a20fce8cf04414f31f2c762d Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:30 +0100
Subject: [PATCH 30/32] liquid: move rpcuser definition to module
---
modules/liquid.nix | 6 +++---
modules/presets/secure-node.nix | 1 -
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/modules/liquid.nix b/modules/liquid.nix
index 354e17921..7158cf0c5 100644
--- a/modules/liquid.nix
+++ b/modules/liquid.nix
@@ -30,7 +30,7 @@ let
rpcbind=${cfg.rpc.address}
rpcconnect=${cfg.rpc.address}
${lib.concatMapStrings (rpcallowip: "rpcallowip=${rpcallowip}\n") cfg.rpcallowip}
- ${optionalString (cfg.rpcuser != null) "rpcuser=${cfg.rpcuser}"}
+ rpcuser=${cfg.rpcuser}
${optionalString (cfg.rpcpassword != null) "rpcpassword=${cfg.rpcpassword}"}
mainchainrpchost=${config.services.bitcoind.rpc.address}
mainchainrpcport=${toString config.services.bitcoind.rpc.port}
@@ -138,8 +138,8 @@ in {
'';
};
rpcuser = mkOption {
- type = types.nullOr types.str;
- default = null;
+ type = types.str;
+ default = "liquidrpc";
description = "Username for JSON-RPC connections";
};
rpcpassword = mkOption {
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 0b1e4b637..90a16ba7e 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -48,7 +48,6 @@ in {
};
services.liquidd = {
- rpcuser = "liquidrpc";
prune = 1000;
validatepegin = true;
listen = true;
From 352fc4e8fe6c24ff856464d9c53997b96197130b Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:31 +0100
Subject: [PATCH 31/32] liquid: remove insecure and redundant option
'rpcpassword'
---
modules/liquid.nix | 6 ------
1 file changed, 6 deletions(-)
diff --git a/modules/liquid.nix b/modules/liquid.nix
index 7158cf0c5..6e833217f 100644
--- a/modules/liquid.nix
+++ b/modules/liquid.nix
@@ -31,7 +31,6 @@ let
rpcconnect=${cfg.rpc.address}
${lib.concatMapStrings (rpcallowip: "rpcallowip=${rpcallowip}\n") cfg.rpcallowip}
rpcuser=${cfg.rpcuser}
- ${optionalString (cfg.rpcpassword != null) "rpcpassword=${cfg.rpcpassword}"}
mainchainrpchost=${config.services.bitcoind.rpc.address}
mainchainrpcport=${toString config.services.bitcoind.rpc.port}
mainchainrpcuser=${config.services.bitcoind.rpc.users.public.name}
@@ -142,11 +141,6 @@ in {
default = "liquidrpc";
description = "Username for JSON-RPC connections";
};
- rpcpassword = mkOption {
- type = types.nullOr types.str;
- default = null;
- description = "Password for JSON-RPC connections";
- };
testnet = mkOption {
type = types.bool;
default = false;
From e2922eb4ce6b820fd1bf698c6aadce5d5f4d27c6 Mon Sep 17 00:00:00 2001
From: Erik Arvstedt
Date: Thu, 14 Jan 2021 13:24:32 +0100
Subject: [PATCH 32/32] move rpc thread count setting to lightning modules
---
modules/clightning.nix | 7 ++++++-
modules/lnd.nix | 7 ++++++-
modules/presets/secure-node.nix | 3 ---
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/modules/clightning.nix b/modules/clightning.nix
index 04af32bd7..544782b9e 100644
--- a/modules/clightning.nix
+++ b/modules/clightning.nix
@@ -95,7 +95,12 @@ in {
};
config = mkIf cfg.enable {
- services.bitcoind.enable = true;
+ services.bitcoind = {
+ enable = true;
+ # Increase rpc thread count due to reports that lightning implementations fail
+ # under high bitcoind rpc load
+ rpc.threads = 16;
+ };
environment.systemPackages = [ nbPkgs.clightning (hiPrio cfg.cli) ];
users.users.${cfg.user} = {
diff --git a/modules/lnd.nix b/modules/lnd.nix
index 5a8629078..e8fb9c7bf 100644
--- a/modules/lnd.nix
+++ b/modules/lnd.nix
@@ -154,7 +154,12 @@ in {
}
];
- services.bitcoind.enable = true;
+ services.bitcoind = {
+ enable = true;
+ # Increase rpc thread count due to reports that lightning implementations fail
+ # under high bitcoind rpc load
+ rpc.threads = 16;
+ };
environment.systemPackages = [ cfg.package (hiPrio cfg.cli) ];
diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix
index 90a16ba7e..a0472c471 100644
--- a/modules/presets/secure-node.nix
+++ b/modules/presets/secure-node.nix
@@ -42,9 +42,6 @@ in {
discover = false;
addresstype = "bech32";
dbCache = 1000;
- # higher rpcthread count due to reports that lightning implementations fail
- # under high bitcoind rpc load
- rpc.threads = 16;
};
services.liquidd = {