Merge fort-nix/nix-bitcoin#425: Misc. improvements
def64a73b8treewide: use TODO-EXTERNAL (Erik Arvstedt)6f37bef2a3netns-isolation: simplify firewall setup (Erik Arvstedt)f52059ce3cdocs: add doc 'Configuration and maintenance' (Erik Arvstedt)94aee8174dusage.md: add section `Managing services` (Erik Arvstedt)8cc7b83da1usage.md: convert to '#' heading syntax (Erik Arvstedt)91fbcfcc77faq.md: reformat (Erik Arvstedt)9e4f4d6b0fbitcoind: add option `txindex` (Erik Arvstedt)10a744a598rtl: add option `extraCurrency` (Erik Arvstedt)62a2602e78electrs: use dataDir for storing extra config (Erik Arvstedt)9bda7305fdservices: add `tor.*` options (Erik Arvstedt)ff24e73ad7onion-addresses: fix files not being copied (Erik Arvstedt)c6fe017aebnetns-isolation: avoid creating service files for disabled services (Erik Arvstedt)017e08ca10btcpayserver: move nbxplorer options to bottom (Erik Arvstedt)e1d869d76cmodules.nix: move rtl to fix topological sorting (Erik Arvstedt)e44cd7ecdcrtl: improve descriptions (Erik Arvstedt)bd275d3a9aminor improvements (Erik Arvstedt)8aa28da110remove `recurring-donations` module (Erik Arvstedt) Pull request description: ACKs for top commit: nixbitcoin: ACKdef64a73b8jonasnick: ACKdef64a73b8Tree-SHA512: 13acd2a3dd73c07f9c31874c8e961f12f39accb48847cbad08479b9a8154b79a6f186819272072dfb5c4768264b81f6e058e9afa57a729db2096784e48352dfd
This commit is contained in:
@@ -157,7 +157,7 @@ let
|
||||
};
|
||||
proxy = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||
description = "Connect through SOCKS5 proxy";
|
||||
};
|
||||
i2p = mkOption {
|
||||
@@ -206,6 +206,11 @@ let
|
||||
Value 0 disables pruning.
|
||||
'';
|
||||
};
|
||||
txindex = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable the transaction index.";
|
||||
};
|
||||
zmqpubrawblock = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
@@ -262,7 +267,7 @@ let
|
||||
'';
|
||||
description = "Binary to connect with the bitcoind instance.";
|
||||
};
|
||||
enforceTor = nbLib.enforceTor;
|
||||
tor = nbLib.tor;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -284,6 +289,7 @@ let
|
||||
''}
|
||||
${optionalString (cfg.dbCache != null) "dbcache=${toString cfg.dbCache}"}
|
||||
prune=${toString cfg.prune}
|
||||
${optionalString cfg.txindex "txindex=1"}
|
||||
${optionalString (cfg.sysperms != null) "sysperms=${if cfg.sysperms then "1" else "0"}"}
|
||||
${optionalString (cfg.disablewallet != null) "disablewallet=${if cfg.disablewallet then "1" else "0"}"}
|
||||
${optionalString (cfg.assumevalid != null) "assumevalid=${cfg.assumevalid}"}
|
||||
@@ -407,7 +413,7 @@ in {
|
||||
Restart = "on-failure";
|
||||
UMask = mkIf cfg.dataDirReadableByGroup "0027";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // nbLib.allowedIPAddresses cfg.enforceTor
|
||||
} // nbLib.allowedIPAddresses cfg.tor.enforce
|
||||
// optionalAttrs zmqServerEnabled nbLib.allowNetlink;
|
||||
};
|
||||
|
||||
|
||||
@@ -3,45 +3,6 @@
|
||||
with lib;
|
||||
let
|
||||
options.services = {
|
||||
nbxplorer = {
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
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";
|
||||
description = "The data directory for nbxplorer.";
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "nbxplorer";
|
||||
description = "The user as which to run nbxplorer.";
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = cfg.nbxplorer.user;
|
||||
description = "The group as which to run nbxplorer.";
|
||||
};
|
||||
enable = mkOption {
|
||||
# This option is only used by netns-isolation
|
||||
internal = true;
|
||||
default = cfg.btcpayserver.enable;
|
||||
};
|
||||
enforceTor = nbLib.enforceTor;
|
||||
};
|
||||
|
||||
btcpayserver = {
|
||||
enable = mkEnableOption "btcpayserver";
|
||||
address = mkOption {
|
||||
@@ -93,7 +54,49 @@ let
|
||||
default = cfg.btcpayserver.user;
|
||||
description = "The group as which to run btcpayserver.";
|
||||
};
|
||||
enforceTor = nbLib.enforceTor;
|
||||
tor.enforce = nbLib.tor.enforce;
|
||||
};
|
||||
|
||||
nbxplorer = {
|
||||
enable = mkOption {
|
||||
# This option is only used by netns-isolation
|
||||
internal = true;
|
||||
default = cfg.btcpayserver.enable;
|
||||
description = ''
|
||||
nbxplorer is always enabled when btcpayserver is enabled.
|
||||
'';
|
||||
};
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
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";
|
||||
description = "The data directory for nbxplorer.";
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "nbxplorer";
|
||||
description = "The user as which to run nbxplorer.";
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = cfg.nbxplorer.user;
|
||||
description = "The group as which to run nbxplorer.";
|
||||
};
|
||||
tor.enforce = nbLib.tor.enforce;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -182,11 +185,11 @@ in {
|
||||
RestartSec = "10s";
|
||||
ReadWritePaths = cfg.nbxplorer.dataDir;
|
||||
MemoryDenyWriteExecute = "false";
|
||||
} // nbLib.allowedIPAddresses cfg.nbxplorer.enforceTor;
|
||||
} // nbLib.allowedIPAddresses cfg.nbxplorer.tor.enforce;
|
||||
};
|
||||
|
||||
systemd.services.btcpayserver = let
|
||||
nbExplorerUrl = "http://${cfg.nbxplorer.address}:${toString cfg.nbxplorer.port}/";
|
||||
nbExplorerUrl = "http://${nbLib.addressWithPort cfg.nbxplorer.address cfg.nbxplorer.port}/";
|
||||
nbExplorerCookie = "${cfg.nbxplorer.dataDir}/${bitcoind.makeNetworkName "Main" "RegTest"}/.cookie";
|
||||
configFile = builtins.toFile "config" (''
|
||||
network=${bitcoind.network}
|
||||
@@ -196,7 +199,8 @@ in {
|
||||
btcexplorerurl=${nbExplorerUrl}
|
||||
btcexplorercookiefile=${nbExplorerCookie}
|
||||
postgres=User ID=${cfg.btcpayserver.user};Host=/run/postgresql;Database=btcpaydb
|
||||
${optionalString (cfg.btcpayserver.rootpath != null) "rootpath=${cfg.btcpayserver.rootpath}"}
|
||||
'' + optionalString (cfg.btcpayserver.rootpath != null) ''
|
||||
rootpath=${cfg.btcpayserver.rootpath}
|
||||
'' + optionalString (cfg.btcpayserver.lightningBackend == "clightning") ''
|
||||
btclightning=type=clightning;server=unix:///${cfg.clightning.dataDir}/bitcoin/lightning-rpc
|
||||
'' + optionalString cfg.btcpayserver.lbtc ''
|
||||
@@ -234,7 +238,7 @@ in {
|
||||
RestartSec = "10s";
|
||||
ReadWritePaths = cfg.btcpayserver.dataDir;
|
||||
MemoryDenyWriteExecute = "false";
|
||||
} // nbLib.allowedIPAddresses cfg.btcpayserver.enforceTor;
|
||||
} // nbLib.allowedIPAddresses cfg.btcpayserver.tor.enforce;
|
||||
}; in self;
|
||||
|
||||
users.users.${cfg.nbxplorer.user} = {
|
||||
|
||||
@@ -9,7 +9,9 @@ let cfg = config.services.clightning.plugins.clboss; in
|
||||
type = types.ints.positive;
|
||||
default = 30000;
|
||||
description = ''
|
||||
Specify target amount (in satoshi) that CLBOSS will leave onchain.
|
||||
Target amount (in satoshi) that CLBOSS will leave on-chain.
|
||||
clboss will only open new channels if this amount is smaller than
|
||||
the funds in your clightning wallet.
|
||||
'';
|
||||
};
|
||||
package = mkOption {
|
||||
@@ -26,6 +28,6 @@ let cfg = config.services.clightning.plugins.clboss; in
|
||||
'';
|
||||
systemd.services.clightning.path = [
|
||||
pkgs.dnsutils
|
||||
] ++ optional config.services.clightning.enforceTor (hiPrio config.nix-bitcoin.torify);
|
||||
] ++ optional config.services.clightning.tor.proxy (hiPrio config.nix-bitcoin.torify);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,14 +16,14 @@ let
|
||||
};
|
||||
proxy = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||
description = ''
|
||||
Socks proxy for connecting to Tor nodes (or for all connections if option always-use-proxy is set).
|
||||
'';
|
||||
};
|
||||
always-use-proxy = mkOption {
|
||||
type = types.bool;
|
||||
default = cfg.enforceTor;
|
||||
default = cfg.tor.proxy;
|
||||
description = ''
|
||||
Always use the proxy, even to connect to normal IP addresses.
|
||||
You can still connect to Unix domain sockets manually.
|
||||
@@ -43,7 +43,16 @@ let
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = "Extra lines appended to the configuration file.";
|
||||
example = ''
|
||||
alias=mynode
|
||||
'';
|
||||
description = ''
|
||||
Extra lines appended to the configuration file.
|
||||
|
||||
See all available options at
|
||||
https://github.com/ElementsProject/lightning/blob/master/doc/lightningd-config.5.md
|
||||
or by running `lightningd --help`.
|
||||
'';
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
@@ -70,7 +79,7 @@ let
|
||||
If left empty, no address is announced.
|
||||
'';
|
||||
};
|
||||
inherit (nbLib) enforceTor;
|
||||
tor = nbLib.tor;
|
||||
};
|
||||
|
||||
cfg = config.services.clightning;
|
||||
@@ -88,6 +97,7 @@ let
|
||||
bitcoin-rpcport=${toString config.services.bitcoind.rpc.port}
|
||||
bitcoin-rpcuser=${config.services.bitcoind.rpc.users.public.name}
|
||||
rpc-file-mode=0660
|
||||
log-timestamps=false
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
|
||||
@@ -123,13 +133,14 @@ in {
|
||||
preStart = ''
|
||||
# The RPC socket has to be removed otherwise we might have stale sockets
|
||||
rm -f ${cfg.networkDir}/lightning-rpc
|
||||
install -m 640 ${configFile} '${cfg.dataDir}/config'
|
||||
umask u=rw,g=r,o=
|
||||
{
|
||||
cat ${configFile}
|
||||
echo "bitcoin-rpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-public)"
|
||||
${optionalString (cfg.getPublicAddressCmd != "") ''
|
||||
echo "announce-addr=$(${cfg.getPublicAddressCmd}):${toString publicPort}"
|
||||
''}
|
||||
} >> '${cfg.dataDir}/config'
|
||||
} > '${cfg.dataDir}/config'
|
||||
'';
|
||||
serviceConfig = nbLib.defaultHardening // {
|
||||
ExecStart = "${nbPkgs.clightning}/bin/lightningd --lightning-dir=${cfg.dataDir}";
|
||||
@@ -145,7 +156,7 @@ in {
|
||||
#
|
||||
# Disable seccomp filtering because clightning depends on this syscall.
|
||||
SystemCallFilter = [];
|
||||
} // nbLib.allowedIPAddresses cfg.enforceTor;
|
||||
} // nbLib.allowedIPAddresses cfg.tor.enforce;
|
||||
# Wait until the rpc socket appears
|
||||
postStart = ''
|
||||
while [[ ! -e ${cfg.networkDir}/lightning-rpc ]]; do
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
presets.secure-node = ./presets/secure-node.nix;
|
||||
rtl = ./rtl.nix;
|
||||
spark-wallet = ./spark-wallet.nix;
|
||||
recurring-donations = ./recurring-donations.nix;
|
||||
lnd = ./lnd.nix;
|
||||
charge-lnd = ./charge-lnd.nix;
|
||||
joinmarket = ./joinmarket.nix;
|
||||
|
||||
@@ -12,7 +12,7 @@ let
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 50001;
|
||||
description = "RPC port.";
|
||||
description = "Port to listen for RPC connections.";
|
||||
};
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
@@ -39,7 +39,7 @@ let
|
||||
default = cfg.user;
|
||||
description = "The group as which to run electrs.";
|
||||
};
|
||||
enforceTor = nbLib.enforceTor;
|
||||
tor.enforce = nbLib.tor.enforce;
|
||||
};
|
||||
|
||||
cfg = config.services.electrs;
|
||||
@@ -74,10 +74,8 @@ in {
|
||||
> electrs.toml
|
||||
'';
|
||||
serviceConfig = nbLib.defaultHardening // {
|
||||
RuntimeDirectory = "electrs";
|
||||
RuntimeDirectoryMode = "700";
|
||||
# electrs only uses the working directory for reading electrs.toml
|
||||
WorkingDirectory = "/run/electrs";
|
||||
WorkingDirectory = cfg.dataDir;
|
||||
ExecStart = ''
|
||||
${config.nix-bitcoin.pkgs.electrs}/bin/electrs \
|
||||
--log-filters=INFO \
|
||||
@@ -95,7 +93,7 @@ in {
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // nbLib.allowedIPAddresses cfg.enforceTor;
|
||||
} // nbLib.allowedIPAddresses cfg.tor.enforce;
|
||||
};
|
||||
|
||||
users.users.${cfg.user} = {
|
||||
|
||||
@@ -29,11 +29,9 @@ let
|
||||
default = cfg.user;
|
||||
description = "The group as which to run JoinMarket.";
|
||||
};
|
||||
# This option is only used by netns-isolation
|
||||
enforceTor = mkOption {
|
||||
readOnly = true;
|
||||
default = true;
|
||||
};
|
||||
# This option is only used by netns-isolation.
|
||||
# Tor is always enabled.
|
||||
tor.enforce = nbLib.tor.enforce;
|
||||
};
|
||||
|
||||
cfg = config.services.joinmarket-ob-watcher;
|
||||
@@ -100,7 +98,7 @@ in {
|
||||
SystemCallFilter = nbLib.defaultHardening.SystemCallFilter ++ [ "mbind" ] ;
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
} // nbLib.allowTor;
|
||||
} // nbLib.allowedIPAddresses cfg.tor.enforce;
|
||||
};
|
||||
|
||||
users.users.${cfg.user} = {
|
||||
|
||||
@@ -50,11 +50,9 @@ let
|
||||
readOnly = true;
|
||||
default = ircServers;
|
||||
};
|
||||
# This option is only used by netns-isolation
|
||||
enforceTor = mkOption {
|
||||
readOnly = true;
|
||||
default = true;
|
||||
};
|
||||
# This option is only used by netns-isolation.
|
||||
# Tor is always enabled.
|
||||
tor.enforce = nbLib.tor.enforce;
|
||||
inherit (nbLib) cliExec;
|
||||
|
||||
yieldgenerator = {
|
||||
@@ -328,7 +326,7 @@ in {
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // nbLib.allowTor;
|
||||
} // nbLib.allowedIPAddresses cfg.tor.enforce;
|
||||
};
|
||||
|
||||
users.users.${cfg.user} = {
|
||||
|
||||
@@ -36,7 +36,7 @@ let
|
||||
};
|
||||
proxy = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||
description = "host:port of SOCKS5 proxy for connnecting to the loop server.";
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
@@ -56,7 +56,7 @@ let
|
||||
'';
|
||||
description = "Binary to connect with the lightning-loop instance.";
|
||||
};
|
||||
enforceTor = nbLib.enforceTor;
|
||||
tor = nbLib.tor;
|
||||
};
|
||||
|
||||
cfg = config.services.lightning-loop;
|
||||
@@ -105,7 +105,7 @@ in {
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // nbLib.allowedIPAddresses cfg.enforceTor;
|
||||
} // nbLib.allowedIPAddresses cfg.tor.enforce;
|
||||
};
|
||||
|
||||
nix-bitcoin.secrets = {
|
||||
|
||||
@@ -36,7 +36,7 @@ let
|
||||
};
|
||||
proxy = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||
description = "host:port of SOCKS5 proxy for connnecting to the pool auction server.";
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
@@ -56,7 +56,7 @@ let
|
||||
'';
|
||||
description = "Binary to connect with the lightning-pool instance.";
|
||||
};
|
||||
enforceTor = nbLib.enforceTor;
|
||||
tor = nbLib.tor;
|
||||
};
|
||||
|
||||
cfg = config.services.lightning-pool;
|
||||
@@ -102,7 +102,7 @@ in {
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // (nbLib.allowedIPAddresses cfg.enforceTor)
|
||||
} // (nbLib.allowedIPAddresses cfg.tor.enforce)
|
||||
// nbLib.allowNetlink; # required by gRPC-Go
|
||||
};
|
||||
};
|
||||
|
||||
@@ -98,7 +98,7 @@ let
|
||||
};
|
||||
proxy = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||
description = "Connect through SOCKS5 proxy";
|
||||
};
|
||||
dbCache = mkOption {
|
||||
@@ -156,7 +156,7 @@ let
|
||||
'';
|
||||
description = "Binary for managing liquid swaps.";
|
||||
};
|
||||
enforceTor = nbLib.enforceTor;
|
||||
tor = nbLib.tor;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -271,7 +271,7 @@ in {
|
||||
ExecStart = "${nbPkgs.elementsd}/bin/elementsd -datadir='${cfg.dataDir}'";
|
||||
Restart = "on-failure";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // nbLib.allowedIPAddresses cfg.enforceTor;
|
||||
} // nbLib.allowedIPAddresses cfg.tor.enforce;
|
||||
};
|
||||
|
||||
users.users.${cfg.user} = {
|
||||
|
||||
@@ -46,7 +46,7 @@ let
|
||||
};
|
||||
tor-socks = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = if cfg.enforceTor then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||
description = "Socks proxy for connecting to Tor nodes";
|
||||
};
|
||||
macaroons = mkOption {
|
||||
@@ -117,7 +117,7 @@ let
|
||||
default = "${secretsDir}/lnd-cert";
|
||||
description = "LND TLS certificate path.";
|
||||
};
|
||||
inherit (nbLib) enforceTor;
|
||||
tor = nbLib.tor;
|
||||
};
|
||||
|
||||
cfg = config.services.lnd;
|
||||
@@ -143,7 +143,7 @@ let
|
||||
bitcoin.active=1
|
||||
bitcoin.node=bitcoind
|
||||
|
||||
${optionalString (cfg.enforceTor) "tor.active=true"}
|
||||
${optionalString (cfg.tor.proxy) "tor.active=true"}
|
||||
${optionalString (cfg.tor-socks != null) "tor.socks=${cfg.tor-socks}"}
|
||||
|
||||
bitcoind.rpchost=${bitcoindRpcAddress}:${toString bitcoind.rpc.port}
|
||||
@@ -277,7 +277,7 @@ in {
|
||||
'') (attrNames cfg.macaroons)}
|
||||
'')
|
||||
];
|
||||
} // nbLib.allowedIPAddresses cfg.enforceTor;
|
||||
} // nbLib.allowedIPAddresses cfg.tor.enforce;
|
||||
};
|
||||
|
||||
users.users.${cfg.user} = {
|
||||
|
||||
@@ -12,20 +12,19 @@
|
||||
./bitcoind.nix
|
||||
./clightning.nix
|
||||
./clightning-plugins
|
||||
./rtl.nix
|
||||
./spark-wallet.nix
|
||||
./lnd.nix
|
||||
./lnd-rest-onion-service.nix # Requires onion-addresses.nix
|
||||
./lightning-loop.nix
|
||||
./lightning-pool.nix
|
||||
./charge-lnd.nix
|
||||
./rtl.nix
|
||||
./electrs.nix
|
||||
./liquid.nix
|
||||
./btcpayserver.nix
|
||||
./joinmarket.nix
|
||||
./joinmarket-ob-watcher.nix
|
||||
./hardware-wallets.nix
|
||||
./recurring-donations.nix
|
||||
|
||||
# Support features
|
||||
./versioning.nix
|
||||
|
||||
@@ -70,7 +70,8 @@ let
|
||||
# and
|
||||
# availableNetns.clighting = [ "bitcoind" ];
|
||||
#
|
||||
# FIXME: Although negligible for our purposes, this calculation's runtime
|
||||
# TODO-EXTERNAL:
|
||||
# Although negligible for our purposes, this calculation's runtime
|
||||
# is in the order of (number of connections * number of services),
|
||||
# because attrsets and lists are fully copied on each update with '//' or '++'.
|
||||
# This can only be improved with an update in the nix language.
|
||||
@@ -156,7 +157,9 @@ in {
|
||||
peer = "nb-veth-br-${toString v.id}";
|
||||
inherit (v) netnsName;
|
||||
nsenter = "${pkgs.utillinux}/bin/nsenter";
|
||||
allowedAddresses = concatMapStringsSep "," (available: netns.${available}.address) v.availableNetns;
|
||||
allowedNetnsAddresses = map (available: netns.${available}.address) v.availableNetns;
|
||||
allowedAddresses = concatStringsSep ","
|
||||
([ "127.0.0.1,${bridgeIp},${v.address}" ] ++ allowedNetnsAddresses);
|
||||
|
||||
setup = ''
|
||||
${ip} netns add ${netnsName}
|
||||
@@ -176,17 +179,13 @@ in {
|
||||
${ip} route add default via ${bridgeIp}
|
||||
|
||||
${iptables} -w -P INPUT DROP
|
||||
${iptables} -w -A INPUT -s 127.0.0.1,${bridgeIp},${v.address} -j ACCEPT
|
||||
# allow return traffic to outgoing connections initiated by the service itself
|
||||
${iptables} -w -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
|
||||
'' + optionalString (config.services.${n}.enforceTor or false) ''
|
||||
${iptables} -w -P OUTPUT DROP
|
||||
${iptables} -w -A OUTPUT -d 127.0.0.1,${bridgeIp},${v.address} -j ACCEPT
|
||||
'' + optionalString (v.availableNetns != []) ''
|
||||
${iptables} -w -A INPUT -s ${allowedAddresses} -j ACCEPT
|
||||
'' + optionalString (config.services.${n}.tor.enforce or false) ''
|
||||
${iptables} -w -P OUTPUT DROP
|
||||
${iptables} -w -A OUTPUT -d ${allowedAddresses} -j ACCEPT
|
||||
'';
|
||||
|
||||
script = name: src: pkgs.writers.writeDash name ''
|
||||
set -e
|
||||
${src}
|
||||
@@ -246,10 +245,6 @@ in {
|
||||
id = 17;
|
||||
# communicates with clightning over lightning-rpc socket
|
||||
};
|
||||
recurring-donations = {
|
||||
id = 20;
|
||||
# communicates with clightning over lightning-rpc socket
|
||||
};
|
||||
nginx = {
|
||||
id = 21;
|
||||
};
|
||||
@@ -336,14 +331,16 @@ in {
|
||||
payjoinAddress = netns.joinmarket.address;
|
||||
cliExec = mkCliExec "joinmarket";
|
||||
};
|
||||
systemd.services.joinmarket-yieldgenerator.serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-joinmarket";
|
||||
systemd.services.joinmarket-yieldgenerator = mkIf config.services.joinmarket.yieldgenerator.enable {
|
||||
serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-joinmarket";
|
||||
};
|
||||
|
||||
services.joinmarket-ob-watcher.address = netns.joinmarket-ob-watcher.address;
|
||||
|
||||
services.lightning-pool.rpcAddress = netns.lightning-pool.address;
|
||||
|
||||
services.rtl.address = netns.rtl.address;
|
||||
systemd.services.cl-rest = {
|
||||
systemd.services.cl-rest = mkIf config.services.rtl.cl-rest.enable {
|
||||
serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-rtl";
|
||||
requires = [ "netns-rtl.service" ] ;
|
||||
after = [ "netns-rtl.service" ];
|
||||
|
||||
@@ -35,7 +35,7 @@ with lib;
|
||||
runAsUserCmd = mkOption {
|
||||
readOnly = true;
|
||||
default = if config.security.doas.enable
|
||||
# TODO: Use absolute path until https://github.com/NixOS/nixpkgs/pull/133622 is available.
|
||||
# TODO-EXTERNAL: Use absolute path until https://github.com/NixOS/nixpkgs/pull/133622 is available.
|
||||
then "/run/wrappers/bin/doas -u"
|
||||
else "sudo -u";
|
||||
};
|
||||
|
||||
@@ -7,6 +7,16 @@ let
|
||||
mkRemovedOptionModule [ "services" service "announce-tor" ] ''
|
||||
Use option `nix-bitcoin.onionServices.${service}.public` instead.
|
||||
'';
|
||||
|
||||
mkSplitEnforceTorOption = service:
|
||||
(mkRemovedOptionModule [ "services" service "enforceTor" ] ''
|
||||
The option has been split into options `tor.proxy` and `tor.enforce`.
|
||||
Set `tor.proxy = true` to proxy outgoing connections with Tor.
|
||||
Set `tor.enforce = true` to only allow connections (incoming and outgoing) through Tor.
|
||||
'');
|
||||
mkRenamedEnforceTorOption = service:
|
||||
(mkRenamedOptionModule [ "services" service "enforceTor" ] [ "services" service "tor" "enforce" ]);
|
||||
|
||||
in {
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "services" "bitcoind" "bind" ] [ "services" "bitcoind" "address" ])
|
||||
@@ -33,5 +43,20 @@ in {
|
||||
bitcoin peer connections for syncing blocks. This performs well on low and high
|
||||
memory systems.
|
||||
'')
|
||||
];
|
||||
] ++
|
||||
# 0.0.59
|
||||
(map mkSplitEnforceTorOption [
|
||||
"clightning"
|
||||
"lightning-loop"
|
||||
"lightning-pool"
|
||||
"liquid"
|
||||
"lnd"
|
||||
"spark-wallet"
|
||||
"bitcoind"
|
||||
]) ++
|
||||
(map mkRenamedEnforceTorOption [
|
||||
"btcpayserver"
|
||||
"rtl"
|
||||
"electrs"
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -58,8 +58,20 @@ in {
|
||||
CapabilityBoundingSet = "CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_IPC_OWNER";
|
||||
};
|
||||
script = ''
|
||||
waitForFile() {
|
||||
file=$1
|
||||
for ((i=0; i<300; i++)); do
|
||||
if [[ -e $file ]]; then
|
||||
return;
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
echo "Error: File $file did not appear after 30 sec."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Wait until tor is up
|
||||
until [[ -e /var/lib/tor/state ]]; do sleep 0.1; done
|
||||
waitForFile /var/lib/tor/state
|
||||
|
||||
cd ${cfg.dataDir}
|
||||
rm -rf *
|
||||
@@ -71,22 +83,20 @@ in {
|
||||
${concatMapStrings
|
||||
(service: ''
|
||||
onionFile=/var/lib/tor/onion/${service}/hostname
|
||||
if [[ -e $onionFile ]]; then
|
||||
cp $onionFile ${user}/${service}
|
||||
chown ${user} ${user}/${service}
|
||||
fi
|
||||
waitForFile $onionFile
|
||||
cp $onionFile ${user}/${service}
|
||||
chown ${user} ${user}/${service}
|
||||
'')
|
||||
cfg.access.${user}
|
||||
}
|
||||
}
|
||||
'')
|
||||
(builtins.attrNames cfg.access)
|
||||
}
|
||||
|
||||
${concatMapStrings (service: ''
|
||||
onionFile=/var/lib/tor/onion/${service}/hostname
|
||||
if [[ -e $onionFile ]]; then
|
||||
install -D -o ${config.systemd.services.${service}.serviceConfig.User} -m 400 $onionFile services/${service}
|
||||
fi
|
||||
waitForFile $onionFile
|
||||
install -D -o ${config.systemd.services.${service}.serviceConfig.User} -m 400 $onionFile services/${service}
|
||||
'') cfg.services}
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -1,27 +1,43 @@
|
||||
{ lib, config, ... }:
|
||||
let
|
||||
defaultTrue = lib.mkDefault true;
|
||||
defaultEnableTorProxy = {
|
||||
tor.proxy = defaultTrue;
|
||||
tor.enforce = defaultTrue;
|
||||
};
|
||||
defaultEnforceTor = {
|
||||
tor.enforce = defaultTrue;
|
||||
};
|
||||
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;
|
||||
# Use Tor as a proxy for outgoing connections
|
||||
# and restrict all connections to Tor
|
||||
#
|
||||
bitcoind = defaultEnableTorProxy;
|
||||
clightning = defaultEnableTorProxy;
|
||||
lnd = defaultEnableTorProxy;
|
||||
lightning-loop = defaultEnableTorProxy;
|
||||
liquidd = defaultEnableTorProxy;
|
||||
# TODO-EXTERNAL:
|
||||
# disable Tor enforcement until btcpayserver can fetch rates over Tor
|
||||
# btcpayserver.enforceTor = true;
|
||||
nbxplorer.enforceTor = true;
|
||||
spark-wallet.enforceTor = true;
|
||||
recurring-donations.enforceTor = true;
|
||||
lightning-pool.enforceTor = true;
|
||||
rtl.enforceTor = true;
|
||||
# btcpayserver = defaultEnableTorProxy;
|
||||
spark-wallet = defaultEnableTorProxy;
|
||||
lightning-pool = defaultEnableTorProxy;
|
||||
|
||||
# These services don't make outgoing connections
|
||||
# (or use Tor by default in case of joinmarket)
|
||||
# but we restrict them to Tor just to be safe.
|
||||
#
|
||||
electrs = defaultEnforceTor;
|
||||
nbxplorer = defaultEnforceTor;
|
||||
rtl = defaultEnforceTor;
|
||||
joinmarket = defaultEnforceTor;
|
||||
joinmarket-ob-watcher = defaultEnforceTor;
|
||||
};
|
||||
|
||||
# Add onion services for incoming connections
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
options.services.recurring-donations = {
|
||||
enable = mkEnableOption "recurring-donations";
|
||||
tallycoin = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
description = ''
|
||||
This option is used to specify tallycoin donation receivers using an
|
||||
attribute set. For example the following setting instructs the module
|
||||
to repeatedly send 1000 satoshis to djbooth007.
|
||||
{
|
||||
"djbooth007" = 1000;
|
||||
}
|
||||
'';
|
||||
};
|
||||
interval = mkOption {
|
||||
type = types.str;
|
||||
default = "Mon *-*-* 00:00:00";
|
||||
description = ''
|
||||
Schedules the donations. Default is weekly on Mon 00:00:00. See `man
|
||||
systemd.time` for further options.
|
||||
'';
|
||||
};
|
||||
randomizedDelaySec = mkOption {
|
||||
type = types.int;
|
||||
default = 86400;
|
||||
description = ''
|
||||
Random delay to add to scheduled time for donation. Default is one day.
|
||||
'';
|
||||
};
|
||||
enforceTor = nbLib.enforceTor;
|
||||
};
|
||||
|
||||
cfg = config.services.recurring-donations;
|
||||
nbLib = config.nix-bitcoin.lib;
|
||||
recurring-donations-script = pkgs.writeScript "recurring-donations.sh" ''
|
||||
LNCLI="${config.nix-bitcoin.pkgs.clightning}/bin/lightning-cli --lightning-dir=${config.services.clightning.dataDir}"
|
||||
pay_tallycoin() {
|
||||
NAME=$1
|
||||
AMOUNT=$2
|
||||
echo "Attempting to pay $AMOUNT sat to $NAME"
|
||||
INVOICE=$(curl --socks5-hostname ${config.nix-bitcoin.torClientAddressWithPort} -d "satoshi_amount=$AMOUNT&payment_method=ln&id=$NAME&type=profile" -X POST https://api.tallyco.in/v1/payment/request/ | jq -r '.lightning_pay_request') 2> /dev/null
|
||||
if [ -z "$INVOICE" ] || [ "$INVOICE" = "null" ]; then
|
||||
echo "ERROR: did not get invoice from tallycoin"
|
||||
return
|
||||
fi
|
||||
# Decode invoice and compare amount with requested amount
|
||||
DECODED_AMOUNT=$($LNCLI decodepay "$INVOICE" | jq -r '.amount_msat' | head -c -8)
|
||||
if [ -z "$DECODED_AMOUNT" ] || [ "$DECODED_AMOUNT" = "null" ]; then
|
||||
echo "ERROR: did not get response from clightning"
|
||||
return
|
||||
fi
|
||||
if [ $DECODED_AMOUNT -eq $AMOUNT ]; then
|
||||
echo "Paying with invoice $INVOICE"
|
||||
$LNCLI pay "$INVOICE"
|
||||
else
|
||||
echo "ERROR: requested amount and invoice amount do not match. $AMOUNT vs $DECODED_AMOUNT"
|
||||
return
|
||||
fi
|
||||
}
|
||||
${ builtins.foldl'
|
||||
(x: receiver: x +
|
||||
''
|
||||
pay_tallycoin ${receiver} ${toString (builtins.getAttr receiver cfg.tallycoin)}
|
||||
'')
|
||||
""
|
||||
(builtins.attrNames cfg.tallycoin)
|
||||
}
|
||||
'';
|
||||
in {
|
||||
inherit options;
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.clightning.enable = true;
|
||||
|
||||
systemd.services.recurring-donations = {
|
||||
requires = [ "clightning.service" ];
|
||||
after = [ "clightning.service" ];
|
||||
path = with pkgs; [ nix-bitcoin.clightning curl jq ];
|
||||
serviceConfig = nbLib.defaultHardening // {
|
||||
ExecStart = "${pkgs.bash}/bin/bash ${recurring-donations-script}";
|
||||
User = "recurring-donations";
|
||||
Type = "oneshot";
|
||||
} // nbLib.allowedIPAddresses cfg.enforceTor;
|
||||
};
|
||||
systemd.timers.recurring-donations = {
|
||||
requires = [ "clightning.service" ];
|
||||
after = [ "clightning.service" ];
|
||||
timerConfig = {
|
||||
Unit = "recurring-donations.service";
|
||||
OnCalendar = cfg.interval;
|
||||
RandomizedDelaySec = toString cfg.randomizedDelaySec;
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
users.users.recurring-donations = {
|
||||
isSystemUser = true;
|
||||
group = "recurring-donations";
|
||||
extraGroups = [ config.services.clightning.group ];
|
||||
};
|
||||
users.groups.recurring-donations = {};
|
||||
};
|
||||
}
|
||||
@@ -23,12 +23,12 @@ let
|
||||
clightning = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Add a node interface for clightning.";
|
||||
description = "Enable the clightning node interface.";
|
||||
};
|
||||
lnd = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Add a node interface for lnd.";
|
||||
description = "Enable the lnd node interface.";
|
||||
};
|
||||
reverseOrder = mkOption {
|
||||
type = types.bool;
|
||||
@@ -49,11 +49,36 @@ let
|
||||
default = false;
|
||||
description = "Enable the Night UI Theme.";
|
||||
};
|
||||
extraCurrency = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
example = "USD";
|
||||
description = ''
|
||||
Currency code (ISO 4217) of the extra currency used for displaying balances.
|
||||
When set, this option enables online currency rate fetching.
|
||||
Warning: Rate fetching requires outgoing clearnet connections, so option
|
||||
`tor.enforce` is automatically disabled.
|
||||
'';
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "rtl";
|
||||
description = "The user as which to run RTL.";
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = cfg.user;
|
||||
description = "The group as which to run RTL.";
|
||||
};
|
||||
cl-rest = {
|
||||
enable = mkOption {
|
||||
readOnly = true;
|
||||
type = types.bool;
|
||||
default = cfg.nodes.clightning;
|
||||
description = "Enable c-lightning-REST server.";
|
||||
description = ''
|
||||
Enable c-lightning-REST server. This service is required for
|
||||
clightning support and is automatically enabled.
|
||||
'';
|
||||
};
|
||||
address = mkOption {
|
||||
readOnly = true;
|
||||
@@ -75,17 +100,7 @@ let
|
||||
description = "Swagger API documentation server port.";
|
||||
};
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "rtl";
|
||||
description = "The user as which to run RTL.";
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = cfg.user;
|
||||
description = "The group as which to run RTL.";
|
||||
};
|
||||
inherit (nbLib) enforceTor;
|
||||
tor.enforce = nbLib.tor.enforce;
|
||||
};
|
||||
|
||||
cfg = config.services.rtl;
|
||||
@@ -114,7 +129,10 @@ let
|
||||
''"channelBackupPath": "${cfg.dataDir}/backup/lnd",''
|
||||
}
|
||||
"logLevel": "INFO",
|
||||
"fiatConversion": false,
|
||||
"fiatConversion": ${if cfg.extraCurrency == null then "false" else "true"},
|
||||
${optionalString (cfg.extraCurrency != null)
|
||||
''"currencyUnit": "${cfg.extraCurrency}",''
|
||||
}
|
||||
${optionalString (isLnd && cfg.loop)
|
||||
''"swapServerUrl": "https://${nbLib.addressWithPort lightning-loop.restAddress lightning-loop.restPort}",''
|
||||
}
|
||||
@@ -186,6 +204,8 @@ in {
|
||||
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
|
||||
];
|
||||
|
||||
services.rtl.tor.enforce = mkIf (cfg.extraCurrency != null) false;
|
||||
|
||||
systemd.services.rtl = rec {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = optional cfg.nodes.clightning "cl-rest.service" ++
|
||||
@@ -210,7 +230,7 @@ in {
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // nbLib.allowedIPAddresses cfg.enforceTor
|
||||
} // nbLib.allowedIPAddresses cfg.tor.enforce
|
||||
// nbLib.nodejs;
|
||||
};
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ let
|
||||
default = cfg.user;
|
||||
description = "The group as which to run spark-wallet.";
|
||||
};
|
||||
inherit (nbLib) enforceTor;
|
||||
tor = nbLib.tor;
|
||||
};
|
||||
|
||||
cfg = config.services.spark-wallet;
|
||||
@@ -57,7 +57,7 @@ let
|
||||
--ln-path '${clightning.networkDir}' \
|
||||
--host ${cfg.address} --port ${toString cfg.port} \
|
||||
--config '${config.nix-bitcoin.secretsDir}/spark-wallet-login' \
|
||||
${optionalString cfg.enforceTor torRateProvider} \
|
||||
${optionalString cfg.tor.proxy torRateProvider} \
|
||||
$publicURL \
|
||||
--pairing-qr --print-key ${cfg.extraArgs}
|
||||
'';
|
||||
@@ -76,7 +76,7 @@ in {
|
||||
User = cfg.user;
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
} // nbLib.allowedIPAddresses cfg.enforceTor
|
||||
} // nbLib.allowedIPAddresses cfg.tor.enforce
|
||||
// nbLib.nodejs;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user