Merge #312: Refactorings, cleanups
0a2c8e4864
run-tests: add option --copy-src (Erik Arvstedt)803584a288
backups: don't use hardcoded secrets dir (Erik Arvstedt)c29d44b49a
ci: use 'cachix watch-exec' (Erik Arvstedt)6a32812412
services: add names for systemd helper scripts (Erik Arvstedt)6982699613
services: use consistent layout (Erik Arvstedt)a43534dda0
services: improve config file setup (Erik Arvstedt)18f2002cf0
joinmarket-yieldgenerator: improve systemd journal output (Erik Arvstedt)9d0b8c8f6f
joinmarket-ob-watcher: use DynamicUser (Erik Arvstedt)e9c98f415c
joinmarket: explain need for tor control socket (Erik Arvstedt)d9c87b6a8f
joinmarket: fix wallet creation (Erik Arvstedt)7458350108
treewide: remove deprecated types.loaOf (Erik Arvstedt)9cf038939c
treewide: use mkEnableOption (Erik Arvstedt)7a97304f13
treewide: remove unit descriptions (Erik Arvstedt)a942177ecf
treewide: remove user descriptions (Erik Arvstedt)4f6ff408ef
treewide: remove unneeded string literals (Erik Arvstedt)e6a6c721c1
treewide: streamline 'extraConfig' descriptions (Erik Arvstedt)e774c045de
treewide: fix formatting (Erik Arvstedt)0b5b29a2a3
netns-isolation: simplify permission definition for netns-exec (Erik Arvstedt)a587a2b02a
defaultHardening: explain where @system-service is defined (Erik Arvstedt)bb3a69797e
README: minor improvements (Erik Arvstedt)13fc9dfabf
examples: improve introductory comments (Erik Arvstedt)af2040f4c4
netns-isolation: use 'true' for systemd option (Erik Arvstedt)c246bbb36e
bitcoind, clightning, lnd: improve descriptions (Erik Arvstedt)7533f12ef1
bitcoind, clightning, run-tests: minor refactoring (Erik Arvstedt)41fe9b0c1d
elementsd: minor refactoring (Erik Arvstedt)f0850d3f23
btcpayserver: reorder config settings (Erik Arvstedt)d1c0ea9f85
btcpayserver: add missing systemd postgresql dependency (Erik Arvstedt) Pull request description: ACKs for top commit: jonasnick: ACK0a2c8e4864
Tree-SHA512: 5c81b36042fbb2f016c8e58ba9e05ef3389d5376b8df713d3258d2cd0b6a9239904531171aca8e49bea7039341d5fa91aa9474c6d98de849c25ede52deccc5a3
This commit is contained in:
commit
f9683889d9
@ -43,7 +43,7 @@ running nix-bitcoin does not require any previous experience with the Nix ecosys
|
|||||||
|
|
||||||
Examples
|
Examples
|
||||||
---
|
---
|
||||||
See the [examples directory](examples/README.md).
|
See [here for examples](examples/README.md).
|
||||||
|
|
||||||
Features
|
Features
|
||||||
---
|
---
|
||||||
@ -76,7 +76,7 @@ NixOS modules
|
|||||||
* Helper
|
* Helper
|
||||||
* [netns-isolation](modules/netns-isolation.nix): isolates applications on the network-level via network namespaces
|
* [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
|
* [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
|
* [backups](modules/backups.nix): 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`)
|
* [operator](modules/operator.nix): adds non-root user `operator` who has access to client tools (e.g. `bitcoin-cli`, `lightning-cli`)
|
||||||
|
|
||||||
Security
|
Security
|
||||||
|
@ -11,18 +11,8 @@ cachixCache=nix-bitcoin
|
|||||||
|
|
||||||
trap 'echo Error at line $LINENO' ERR
|
trap 'echo Error at line $LINENO' ERR
|
||||||
|
|
||||||
atExit() {
|
|
||||||
rm -rf $tmpDir
|
|
||||||
if [[ -v cachixPid ]]; then stopCachix; fi
|
|
||||||
}
|
|
||||||
tmpDir=$(mktemp -d -p /tmp)
|
tmpDir=$(mktemp -d -p /tmp)
|
||||||
trap atExit EXIT
|
trap "rm -rf $tmpDir" EXIT
|
||||||
|
|
||||||
stopCachix() {
|
|
||||||
kill $cachixPid 2>/dev/null || true
|
|
||||||
# Wait for cachix to finish
|
|
||||||
tail --pid=$cachixPid -f /dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
## Instantiate
|
## Instantiate
|
||||||
|
|
||||||
@ -43,14 +33,14 @@ fi
|
|||||||
|
|
||||||
if [[ $CACHIX_SIGNING_KEY ]]; then
|
if [[ $CACHIX_SIGNING_KEY ]]; then
|
||||||
# Speed up task by uploading store paths as soon as they are created
|
# Speed up task by uploading store paths as soon as they are created
|
||||||
cachix push $cachixCache --watch-store &
|
buildCmd="cachix watch-exec $cachixCache nix-build --"
|
||||||
cachixPid=$!
|
else
|
||||||
|
buildCmd=nix-build
|
||||||
fi
|
fi
|
||||||
|
|
||||||
nix-build --out-link $tmpDir/result $tmpDir/drv >/dev/null
|
$buildCmd --out-link $tmpDir/result $tmpDir/drv >/dev/null
|
||||||
|
|
||||||
if [[ $CACHIX_SIGNING_KEY ]]; then
|
if [[ $CACHIX_SIGNING_KEY ]]; then
|
||||||
stopCachix
|
|
||||||
cachix push $cachixCache $outPath
|
cachix push $cachixCache $outPath
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ set -euo pipefail
|
|||||||
# Running this script leaves no traces on your host system.
|
# Running this script leaves no traces on your host system.
|
||||||
|
|
||||||
# This demo is a template for your own experiments.
|
# This demo is a template for your own experiments.
|
||||||
# Feel free to modify or to run nix-shell and execute individual statements of this
|
# Run with option `--interactive` or `-i` to start a shell for interacting with
|
||||||
# script in the interactive shell.
|
# the node.
|
||||||
|
|
||||||
if [[ ! -v IN_NIX_SHELL ]]; then
|
if [[ ! -v IN_NIX_SHELL ]]; then
|
||||||
echo "Running script in nix shell env..."
|
echo "Running script in nix shell env..."
|
||||||
|
@ -5,8 +5,8 @@ set -euo pipefail
|
|||||||
# Running this script leaves no traces on your host system.
|
# Running this script leaves no traces on your host system.
|
||||||
|
|
||||||
# This demo is a template for your own experiments.
|
# This demo is a template for your own experiments.
|
||||||
# Feel free to modify or to run nix-shell and execute individual statements of this
|
# Run with option `--interactive` or `-i` to start a shell for interacting with
|
||||||
# script in the interactive shell.
|
# the node.
|
||||||
|
|
||||||
if [[ ! -v IN_NIX_SHELL ]]; then
|
if [[ ! -v IN_NIX_SHELL ]]; then
|
||||||
echo "Running script in nix shell env..."
|
echo "Running script in nix shell env..."
|
||||||
|
@ -5,8 +5,8 @@ set -euo pipefail
|
|||||||
# Running this script leaves no traces on your host system.
|
# Running this script leaves no traces on your host system.
|
||||||
|
|
||||||
# This demo is a template for your own experiments.
|
# This demo is a template for your own experiments.
|
||||||
# Feel free to modify or to run nix-shell and execute individual statements of this
|
# Run with option `--interactive` or `-i` to start a shell for interacting with
|
||||||
# script in the interactive shell.
|
# the node.
|
||||||
|
|
||||||
# MAKE SURE TO REPLACE the SSH identity file if you use this script for
|
# MAKE SURE TO REPLACE the SSH identity file if you use this script for
|
||||||
# anything serious.
|
# anything serious.
|
||||||
|
@ -4,13 +4,15 @@ with lib;
|
|||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.backups;
|
cfg = config.services.backups;
|
||||||
|
secretsDir = config.nix-bitcoin.secretsDir;
|
||||||
|
|
||||||
filelist = pkgs.writeText "filelist.txt" ''
|
filelist = pkgs.writeText "filelist.txt" ''
|
||||||
${optionalString (!cfg.with-bulk-data) "- ${config.services.bitcoind.dataDir}/blocks"}
|
${optionalString (!cfg.with-bulk-data) "- ${config.services.bitcoind.dataDir}/blocks"}
|
||||||
${optionalString (!cfg.with-bulk-data) "- ${config.services.bitcoind.dataDir}/chainstate"}
|
${optionalString (!cfg.with-bulk-data) "- ${config.services.bitcoind.dataDir}/chainstate"}
|
||||||
${config.services.bitcoind.dataDir}
|
${config.services.bitcoind.dataDir}
|
||||||
${config.services.clightning.dataDir}
|
${config.services.clightning.dataDir}
|
||||||
${config.services.lnd.dataDir}
|
${config.services.lnd.dataDir}
|
||||||
/secrets/lnd-seed-mnemonic
|
${secretsDir}/lnd-seed-mnemonic
|
||||||
${optionalString (!cfg.with-bulk-data) "- ${config.services.liquidd.dataDir}/*/blocks"}
|
${optionalString (!cfg.with-bulk-data) "- ${config.services.liquidd.dataDir}/*/blocks"}
|
||||||
${optionalString (!cfg.with-bulk-data) "- ${config.services.liquidd.dataDir}/*/chainstate"}
|
${optionalString (!cfg.with-bulk-data) "- ${config.services.liquidd.dataDir}/*/chainstate"}
|
||||||
${config.services.liquidd.dataDir}
|
${config.services.liquidd.dataDir}
|
||||||
@ -18,7 +20,7 @@ let
|
|||||||
${config.services.nbxplorer.dataDir}
|
${config.services.nbxplorer.dataDir}
|
||||||
${config.services.btcpayserver.dataDir}
|
${config.services.btcpayserver.dataDir}
|
||||||
${config.services.joinmarket.dataDir}
|
${config.services.joinmarket.dataDir}
|
||||||
/secrets/jm-wallet-seed
|
${secretsDir}/jm-wallet-seed
|
||||||
${config.services.postgresqlBackup.location}/btcpaydb.sql.gz
|
${config.services.postgresqlBackup.location}/btcpaydb.sql.gz
|
||||||
/var/lib/tor
|
/var/lib/tor
|
||||||
# Extra files
|
# Extra files
|
||||||
@ -27,7 +29,6 @@ let
|
|||||||
# Exclude all unspecified files and directories
|
# Exclude all unspecified files and directories
|
||||||
- /
|
- /
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in {
|
in {
|
||||||
options.services.backups = {
|
options.services.backups = {
|
||||||
enable = mkEnableOption "Backups service";
|
enable = mkEnableOption "Backups service";
|
||||||
@ -72,7 +73,7 @@ in {
|
|||||||
"--include-filelist" "${filelist}"
|
"--include-filelist" "${filelist}"
|
||||||
"--full-if-older-than" "1M"
|
"--full-if-older-than" "1M"
|
||||||
];
|
];
|
||||||
targetUrl = "${cfg.destination}";
|
targetUrl = cfg.destination;
|
||||||
frequency = cfg.frequency;
|
frequency = cfg.frequency;
|
||||||
secretFile = "${config.nix-bitcoin.secretsDir}/backup-encryption-env";
|
secretFile = "${config.nix-bitcoin.secretsDir}/backup-encryption-env";
|
||||||
};
|
};
|
||||||
|
@ -58,5 +58,5 @@
|
|||||||
"validateaddress"
|
"validateaddress"
|
||||||
"verifymessage"
|
"verifymessage"
|
||||||
# Zmq
|
# Zmq
|
||||||
"getzmqnotifications"
|
"getzmqnotifications"
|
||||||
]
|
]
|
||||||
|
@ -7,7 +7,7 @@ let
|
|||||||
nbLib = config.nix-bitcoin.lib;
|
nbLib = config.nix-bitcoin.lib;
|
||||||
secretsDir = config.nix-bitcoin.secretsDir;
|
secretsDir = config.nix-bitcoin.secretsDir;
|
||||||
|
|
||||||
configFile = pkgs.writeText "bitcoin.conf" ''
|
configFile = builtins.toFile "bitcoin.conf" ''
|
||||||
# We're already logging via journald
|
# We're already logging via journald
|
||||||
nodebuglogfile=1
|
nodebuglogfile=1
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ in {
|
|||||||
par=16
|
par=16
|
||||||
logips=1
|
logips=1
|
||||||
'';
|
'';
|
||||||
description = "Additional configurations to be appended to <filename>bitcoin.conf</filename>.";
|
description = "Extra lines appended to <filename>bitcoin.conf</filename>.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
@ -138,7 +138,7 @@ in {
|
|||||||
alice.passwordHMAC = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
|
alice.passwordHMAC = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
|
||||||
bob.passwordHMAC = "b2dd077cb54591a2f3139e69a897ac$4e71f08d48b4347cf8eff3815c0e25ae2e9a4340474079f55705f40574f4ec99";
|
bob.passwordHMAC = "b2dd077cb54591a2f3139e69a897ac$4e71f08d48b4347cf8eff3815c0e25ae2e9a4340474079f55705f40574f4ec99";
|
||||||
};
|
};
|
||||||
type = with types; loaOf (submodule ({ name, ... }: {
|
type = with types; attrsOf (submodule ({ name, ... }: {
|
||||||
options = {
|
options = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
@ -197,9 +197,7 @@ in {
|
|||||||
listen = mkOption {
|
listen = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = "Accept incoming connections.";
|
||||||
If enabled, the bitcoin service will listen.
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
dataDirReadableByGroup = mkOption {
|
dataDirReadableByGroup = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
@ -228,21 +226,15 @@ in {
|
|||||||
type = types.nullOr (types.ints.between 4 16384);
|
type = types.nullOr (types.ints.between 4 16384);
|
||||||
default = null;
|
default = null;
|
||||||
example = 4000;
|
example = 4000;
|
||||||
description = "Override the default database cache size in megabytes.";
|
description = "Override the default database cache size in MiB.";
|
||||||
};
|
};
|
||||||
prune = mkOption {
|
prune = mkOption {
|
||||||
type = types.ints.unsigned;
|
type = types.ints.unsigned;
|
||||||
default = 0;
|
default = 0;
|
||||||
example = 10000;
|
example = 10000;
|
||||||
description = ''
|
description = ''
|
||||||
Reduce storage requirements by enabling pruning (deleting) of old
|
Automatically prune block files to stay under the specified target size in MiB.
|
||||||
blocks. This allows the pruneblockchain RPC to be called to delete
|
Value 0 disables pruning.
|
||||||
specific blocks, and enables automatic pruning of old blocks if a
|
|
||||||
target size in MiB is provided. This mode is incompatible with -txindex
|
|
||||||
and -rescan. Warning: Reverting this setting requires re-downloading
|
|
||||||
the entire blockchain. ("disable" = disable pruning blocks, "manual"
|
|
||||||
= allow manual pruning via RPC, >=550 = automatically prune block files
|
|
||||||
to stay under the specified target size in MiB)
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
zmqpubrawblock = mkOption {
|
zmqpubrawblock = mkOption {
|
||||||
@ -281,7 +273,7 @@ in {
|
|||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
example = "bech32";
|
example = "bech32";
|
||||||
description = "What type of addresses to use";
|
description = "The type of addresses to use";
|
||||||
};
|
};
|
||||||
cli = mkOption {
|
cli = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
@ -320,7 +312,6 @@ in {
|
|||||||
];
|
];
|
||||||
|
|
||||||
systemd.services.bitcoind = {
|
systemd.services.bitcoind = {
|
||||||
description = "Bitcoin daemon";
|
|
||||||
requires = [ "nix-bitcoin-secrets.target" ];
|
requires = [ "nix-bitcoin-secrets.target" ];
|
||||||
after = [ "network.target" "nix-bitcoin-secrets.target" ];
|
after = [ "network.target" "nix-bitcoin-secrets.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
@ -334,10 +325,10 @@ in {
|
|||||||
in ''
|
in ''
|
||||||
${optionalString cfg.dataDirReadableByGroup "chmod -R g+rX '${cfg.dataDir}/blocks'"}
|
${optionalString cfg.dataDirReadableByGroup "chmod -R g+rX '${cfg.dataDir}/blocks'"}
|
||||||
cfg=$(
|
cfg=$(
|
||||||
cat ${configFile};
|
cat ${configFile}
|
||||||
${extraRpcauth}
|
${extraRpcauth}
|
||||||
${/* Enable bitcoin-cli for group 'bitcoin' */ ""}
|
${/* Enable bitcoin-cli for group 'bitcoin' */ ""}
|
||||||
printf "rpcuser=${cfg.rpc.users.privileged.name}\nrpcpassword="; cat "${secretsDir}/bitcoin-rpcpassword-privileged";
|
printf "rpcuser=${cfg.rpc.users.privileged.name}\nrpcpassword="; cat "${secretsDir}/bitcoin-rpcpassword-privileged"
|
||||||
echo
|
echo
|
||||||
${optionalString (cfg.getPublicAddressCmd != "") ''
|
${optionalString (cfg.getPublicAddressCmd != "") ''
|
||||||
echo "externalip=$(${cfg.getPublicAddressCmd})"
|
echo "externalip=$(${cfg.getPublicAddressCmd})"
|
||||||
@ -351,13 +342,13 @@ in {
|
|||||||
serviceConfig = nbLib.defaultHardening // {
|
serviceConfig = nbLib.defaultHardening // {
|
||||||
Type = "notify";
|
Type = "notify";
|
||||||
NotifyAccess = "all";
|
NotifyAccess = "all";
|
||||||
User = "${cfg.user}";
|
User = cfg.user;
|
||||||
Group = "${cfg.group}";
|
Group = cfg.group;
|
||||||
TimeoutStartSec = 300;
|
TimeoutStartSec = 300;
|
||||||
ExecStart = "${cfg.package}/bin/bitcoind -datadir='${cfg.dataDir}'";
|
ExecStart = "${cfg.package}/bin/bitcoind -datadir='${cfg.dataDir}'";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
UMask = mkIf cfg.dataDirReadableByGroup "0027";
|
UMask = mkIf cfg.dataDirReadableByGroup "0027";
|
||||||
ReadWritePaths = "${cfg.dataDir}";
|
ReadWritePaths = cfg.dataDir;
|
||||||
} // (if cfg.enforceTor
|
} // (if cfg.enforceTor
|
||||||
then nbLib.allowTor
|
then nbLib.allowTor
|
||||||
else nbLib.allowAnyIP)
|
else nbLib.allowAnyIP)
|
||||||
@ -383,16 +374,13 @@ in {
|
|||||||
done
|
done
|
||||||
'';
|
'';
|
||||||
serviceConfig = nbLib.defaultHardening // {
|
serviceConfig = nbLib.defaultHardening // {
|
||||||
User = "${cfg.user}";
|
User = cfg.user;
|
||||||
Group = "${cfg.group}";
|
Group = cfg.group;
|
||||||
ReadWritePaths = "${cfg.dataDir}";
|
ReadWritePaths = cfg.dataDir;
|
||||||
} // nbLib.allowTor;
|
} // nbLib.allowTor;
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users.${cfg.user} = {
|
users.users.${cfg.user}.group = cfg.group;
|
||||||
group = cfg.group;
|
|
||||||
description = "Bitcoin daemon user";
|
|
||||||
};
|
|
||||||
users.groups.${cfg.group} = {};
|
users.groups.${cfg.group} = {};
|
||||||
users.groups.bitcoinrpc = {};
|
users.groups.bitcoinrpc = {};
|
||||||
nix-bitcoin.operator.groups = [ cfg.group ];
|
nix-bitcoin.operator.groups = [ cfg.group ];
|
||||||
|
@ -99,20 +99,34 @@ in {
|
|||||||
services.clightning.enable = mkIf (cfg.btcpayserver.lightningBackend == "clightning") true;
|
services.clightning.enable = mkIf (cfg.btcpayserver.lightningBackend == "clightning") true;
|
||||||
services.lnd.enable = mkIf (cfg.btcpayserver.lightningBackend == "lnd") true;
|
services.lnd.enable = mkIf (cfg.btcpayserver.lightningBackend == "lnd") true;
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
services.bitcoind.rpc.users.btcpayserver = {
|
||||||
"d '${cfg.nbxplorer.dataDir}' 0770 ${cfg.nbxplorer.user} ${cfg.nbxplorer.group} - -"
|
passwordHMACFromFile = true;
|
||||||
"d '${cfg.btcpayserver.dataDir}' 0770 ${cfg.btcpayserver.user} ${cfg.btcpayserver.group} - -"
|
rpcwhitelist = cfg.bitcoind.rpc.users.public.rpcwhitelist ++ [
|
||||||
];
|
"setban"
|
||||||
|
"generatetoaddress"
|
||||||
|
"getpeerinfo"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.lnd.macaroons.btcpayserver = mkIf (cfg.btcpayserver.lightningBackend == "lnd") {
|
||||||
|
inherit (cfg.btcpayserver) user;
|
||||||
|
permissions = ''{"entity":"info","action":"read"},{"entity":"onchain","action":"read"},{"entity":"offchain","action":"read"},{"entity":"address","action":"read"},{"entity":"message","action":"read"},{"entity":"peers","action":"read"},{"entity":"signer","action":"read"},{"entity":"invoices","action":"read"},{"entity":"invoices","action":"write"},{"entity":"address","action":"write"}'';
|
||||||
|
};
|
||||||
|
|
||||||
services.postgresql = {
|
services.postgresql = {
|
||||||
enable = true;
|
enable = true;
|
||||||
ensureDatabases = [ "btcpaydb" ];
|
ensureDatabases = [ "btcpaydb" ];
|
||||||
ensureUsers = [{
|
ensureUsers = [{
|
||||||
name = "${cfg.btcpayserver.user}";
|
name = cfg.btcpayserver.user;
|
||||||
ensurePermissions."DATABASE btcpaydb" = "ALL PRIVILEGES";
|
ensurePermissions."DATABASE btcpaydb" = "ALL PRIVILEGES";
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d '${cfg.nbxplorer.dataDir}' 0770 ${cfg.nbxplorer.user} ${cfg.nbxplorer.group} - -"
|
||||||
|
"d '${cfg.btcpayserver.dataDir}' 0770 ${cfg.btcpayserver.user} ${cfg.btcpayserver.group} - -"
|
||||||
|
];
|
||||||
|
|
||||||
systemd.services.nbxplorer = let
|
systemd.services.nbxplorer = let
|
||||||
configFile = builtins.toFile "config" ''
|
configFile = builtins.toFile "config" ''
|
||||||
network=${config.services.bitcoind.network}
|
network=${config.services.bitcoind.network}
|
||||||
@ -123,12 +137,11 @@ in {
|
|||||||
port=${toString cfg.nbxplorer.port}
|
port=${toString cfg.nbxplorer.port}
|
||||||
'';
|
'';
|
||||||
in {
|
in {
|
||||||
description = "Run nbxplorer";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
requires = [ "bitcoind.service" ];
|
requires = [ "bitcoind.service" ];
|
||||||
after = [ "bitcoind.service" ];
|
after = [ "bitcoind.service" ];
|
||||||
preStart = ''
|
preStart = ''
|
||||||
install -m 600 ${configFile} ${cfg.nbxplorer.dataDir}/settings.config
|
install -m 600 ${configFile} '${cfg.nbxplorer.dataDir}/settings.config'
|
||||||
echo "btcrpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-btcpayserver)" \
|
echo "btcrpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-btcpayserver)" \
|
||||||
>> '${cfg.nbxplorer.dataDir}/settings.config'
|
>> '${cfg.nbxplorer.dataDir}/settings.config'
|
||||||
'';
|
'';
|
||||||
@ -151,13 +164,13 @@ in {
|
|||||||
systemd.services.btcpayserver = let
|
systemd.services.btcpayserver = let
|
||||||
configFile = builtins.toFile "config" (''
|
configFile = builtins.toFile "config" (''
|
||||||
network=${config.services.bitcoind.network}
|
network=${config.services.bitcoind.network}
|
||||||
postgres=User ID=${cfg.btcpayserver.user};Host=/run/postgresql;Database=btcpaydb
|
bind=${cfg.btcpayserver.address}
|
||||||
|
port=${toString cfg.btcpayserver.port}
|
||||||
socksendpoint=${cfg.tor.client.socksListenAddress}
|
socksendpoint=${cfg.tor.client.socksListenAddress}
|
||||||
btcexplorerurl=http://${cfg.nbxplorer.address}:${toString cfg.nbxplorer.port}/
|
btcexplorerurl=http://${cfg.nbxplorer.address}:${toString cfg.nbxplorer.port}/
|
||||||
btcexplorercookiefile=${cfg.nbxplorer.dataDir}/${config.services.bitcoind.makeNetworkName "Main" "RegTest"}/.cookie
|
btcexplorercookiefile=${cfg.nbxplorer.dataDir}/${config.services.bitcoind.makeNetworkName "Main" "RegTest"}/.cookie
|
||||||
bind=${cfg.btcpayserver.address}
|
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}"}
|
||||||
port=${toString cfg.btcpayserver.port}
|
|
||||||
'' + optionalString (cfg.btcpayserver.lightningBackend == "clightning") ''
|
'' + optionalString (cfg.btcpayserver.lightningBackend == "clightning") ''
|
||||||
btclightning=type=clightning;server=unix:///${cfg.clightning.dataDir}/bitcoin/lightning-rpc
|
btclightning=type=clightning;server=unix:///${cfg.clightning.dataDir}/bitcoin/lightning-rpc
|
||||||
'');
|
'');
|
||||||
@ -168,17 +181,17 @@ in {
|
|||||||
"certthumbprint=";
|
"certthumbprint=";
|
||||||
in let self = {
|
in let self = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
requires = [ "nbxplorer.service" ]
|
requires = [ "nbxplorer.service" "postgresql.service" ]
|
||||||
++ optional (cfg.btcpayserver.lightningBackend != null) "${cfg.btcpayserver.lightningBackend}.service";
|
++ optional (cfg.btcpayserver.lightningBackend != null) "${cfg.btcpayserver.lightningBackend}.service";
|
||||||
after = self.requires;
|
after = self.requires;
|
||||||
preStart = ''
|
preStart = ''
|
||||||
install -m 600 ${configFile} ${cfg.btcpayserver.dataDir}/settings.config
|
install -m 600 ${configFile} '${cfg.btcpayserver.dataDir}/settings.config'
|
||||||
${optionalString (cfg.btcpayserver.lightningBackend == "lnd") ''
|
${optionalString (cfg.btcpayserver.lightningBackend == "lnd") ''
|
||||||
{
|
{
|
||||||
echo -n "${lndConfig}";
|
echo -n "${lndConfig}";
|
||||||
${pkgs.openssl}/bin/openssl x509 -noout -fingerprint -sha256 -in ${config.nix-bitcoin.secretsDir}/lnd-cert \
|
${pkgs.openssl}/bin/openssl x509 -noout -fingerprint -sha256 -in ${config.nix-bitcoin.secretsDir}/lnd-cert \
|
||||||
| sed -e 's/.*=//;s/://g';
|
| sed -e 's/.*=//;s/://g';
|
||||||
} >> ${cfg.btcpayserver.dataDir}/settings.config
|
} >> '${cfg.btcpayserver.dataDir}/settings.config'
|
||||||
''}
|
''}
|
||||||
'';
|
'';
|
||||||
serviceConfig = nbLib.defaultHardening // {
|
serviceConfig = nbLib.defaultHardening // {
|
||||||
@ -197,20 +210,13 @@ in {
|
|||||||
);
|
);
|
||||||
}; in self;
|
}; in self;
|
||||||
|
|
||||||
services.lnd.macaroons.btcpayserver = mkIf (cfg.btcpayserver.lightningBackend == "lnd") {
|
|
||||||
inherit (cfg.btcpayserver) user;
|
|
||||||
permissions = ''{"entity":"info","action":"read"},{"entity":"onchain","action":"read"},{"entity":"offchain","action":"read"},{"entity":"address","action":"read"},{"entity":"message","action":"read"},{"entity":"peers","action":"read"},{"entity":"signer","action":"read"},{"entity":"invoices","action":"read"},{"entity":"invoices","action":"write"},{"entity":"address","action":"write"}'';
|
|
||||||
};
|
|
||||||
|
|
||||||
users.users.${cfg.nbxplorer.user} = {
|
users.users.${cfg.nbxplorer.user} = {
|
||||||
description = "nbxplorer user";
|
|
||||||
group = cfg.nbxplorer.group;
|
group = cfg.nbxplorer.group;
|
||||||
extraGroups = [ "bitcoinrpc" ];
|
extraGroups = [ "bitcoinrpc" ];
|
||||||
home = cfg.nbxplorer.dataDir;
|
home = cfg.nbxplorer.dataDir;
|
||||||
};
|
};
|
||||||
users.groups.${cfg.nbxplorer.group} = {};
|
users.groups.${cfg.nbxplorer.group} = {};
|
||||||
users.users.${cfg.btcpayserver.user} = {
|
users.users.${cfg.btcpayserver.user} = {
|
||||||
description = "btcpayserver user";
|
|
||||||
group = cfg.btcpayserver.group;
|
group = cfg.btcpayserver.group;
|
||||||
extraGroups = [ "nbxplorer" ]
|
extraGroups = [ "nbxplorer" ]
|
||||||
++ optional (cfg.btcpayserver.lightningBackend == "clightning") cfg.clightning.user;
|
++ optional (cfg.btcpayserver.lightningBackend == "clightning") cfg.clightning.user;
|
||||||
@ -218,18 +224,12 @@ in {
|
|||||||
};
|
};
|
||||||
users.groups.${cfg.btcpayserver.group} = {};
|
users.groups.${cfg.btcpayserver.group} = {};
|
||||||
|
|
||||||
services.bitcoind.rpc.users.btcpayserver = {
|
nix-bitcoin.secrets = {
|
||||||
passwordHMACFromFile = true;
|
bitcoin-rpcpassword-btcpayserver = {
|
||||||
rpcwhitelist = cfg.bitcoind.rpc.users.public.rpcwhitelist ++ [
|
user = "bitcoin";
|
||||||
"setban"
|
group = "nbxplorer";
|
||||||
"generatetoaddress"
|
};
|
||||||
"getpeerinfo"
|
bitcoin-HMAC-btcpayserver.user = "bitcoin";
|
||||||
];
|
|
||||||
};
|
};
|
||||||
nix-bitcoin.secrets.bitcoin-rpcpassword-btcpayserver = {
|
|
||||||
user = "bitcoin";
|
|
||||||
group = "nbxplorer";
|
|
||||||
};
|
|
||||||
nix-bitcoin.secrets.bitcoin-HMAC-btcpayserver.user = "bitcoin";
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ let
|
|||||||
network=${network}
|
network=${network}
|
||||||
bitcoin-datadir=${config.services.bitcoind.dataDir}
|
bitcoin-datadir=${config.services.bitcoind.dataDir}
|
||||||
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
|
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
|
||||||
always-use-proxy=${if cfg.always-use-proxy then "true" else "false"}
|
always-use-proxy=${boolToString cfg.always-use-proxy}
|
||||||
bind-addr=${cfg.address}:${toString cfg.port}
|
bind-addr=${cfg.address}:${toString cfg.port}
|
||||||
bitcoin-rpcconnect=${config.services.bitcoind.rpc.address}
|
bitcoin-rpcconnect=${config.services.bitcoind.rpc.address}
|
||||||
bitcoin-rpcport=${toString config.services.bitcoind.rpc.port}
|
bitcoin-rpcport=${toString config.services.bitcoind.rpc.port}
|
||||||
@ -21,13 +21,7 @@ let
|
|||||||
'';
|
'';
|
||||||
in {
|
in {
|
||||||
options.services.clightning = {
|
options.services.clightning = {
|
||||||
enable = mkOption {
|
enable = mkEnableOption "clightning";
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
If enabled, the clightning service will be installed.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
@ -41,13 +35,17 @@ in {
|
|||||||
proxy = mkOption {
|
proxy = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = if cfg.enforceTor then config.services.tor.client.socksListenAddress else null;
|
default = if cfg.enforceTor then config.services.tor.client.socksListenAddress else null;
|
||||||
description = "Set a socks proxy to use to connect to Tor nodes (or for all connections if *always-use-proxy* is set)";
|
description = ''
|
||||||
|
Socks proxy for connecting to Tor nodes (or for all connections if option always-use-proxy is set).
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
always-use-proxy = mkOption {
|
always-use-proxy = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = cfg.enforceTor;
|
default = cfg.enforceTor;
|
||||||
description = ''
|
description = ''
|
||||||
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.
|
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 address information.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
@ -63,7 +61,7 @@ in {
|
|||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
type = types.lines;
|
type = types.lines;
|
||||||
default = "";
|
default = "";
|
||||||
description = "Additional lines appended to the config file.";
|
description = "Extra lines appended to the configuration file.";
|
||||||
};
|
};
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
@ -77,8 +75,7 @@ in {
|
|||||||
};
|
};
|
||||||
cli = mkOption {
|
cli = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = pkgs.writeScriptBin "lightning-cli"
|
default = pkgs.writeScriptBin "lightning-cli" ''
|
||||||
''
|
|
||||||
${nbPkgs.clightning}/bin/lightning-cli --lightning-dir='${cfg.dataDir}' "$@"
|
${nbPkgs.clightning}/bin/lightning-cli --lightning-dir='${cfg.dataDir}' "$@"
|
||||||
'';
|
'';
|
||||||
description = "Binary to connect with the clightning instance.";
|
description = "Binary to connect with the clightning instance.";
|
||||||
@ -103,44 +100,34 @@ in {
|
|||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = [ nbPkgs.clightning (hiPrio cfg.cli) ];
|
environment.systemPackages = [ nbPkgs.clightning (hiPrio cfg.cli) ];
|
||||||
users.users.${cfg.user} = {
|
|
||||||
description = "clightning User";
|
|
||||||
group = cfg.group;
|
|
||||||
extraGroups = [ "bitcoinrpc" ];
|
|
||||||
};
|
|
||||||
users.groups.${cfg.group} = {};
|
|
||||||
nix-bitcoin.operator.groups = [ cfg.group ];
|
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
systemd.tmpfiles.rules = [
|
||||||
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
|
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
|
||||||
];
|
];
|
||||||
|
|
||||||
systemd.services.clightning = {
|
systemd.services.clightning = {
|
||||||
description = "Run clightningd";
|
|
||||||
path = [ nbPkgs.bitcoind ];
|
path = [ nbPkgs.bitcoind ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
requires = [ "bitcoind.service" ];
|
requires = [ "bitcoind.service" ];
|
||||||
after = [ "bitcoind.service" ];
|
after = [ "bitcoind.service" ];
|
||||||
preStart = ''
|
preStart = ''
|
||||||
cp ${configFile} ${cfg.dataDir}/config
|
|
||||||
chown -R '${cfg.user}:${cfg.group}' '${cfg.dataDir}'
|
chown -R '${cfg.user}:${cfg.group}' '${cfg.dataDir}'
|
||||||
# The RPC socket has to be removed otherwise we might have stale sockets
|
# The RPC socket has to be removed otherwise we might have stale sockets
|
||||||
rm -f ${cfg.networkDir}/lightning-rpc
|
rm -f ${cfg.networkDir}/lightning-rpc
|
||||||
chmod 640 ${cfg.dataDir}/config
|
install -m 640 ${configFile} '${cfg.dataDir}/config'
|
||||||
{
|
{
|
||||||
echo "bitcoin-rpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-public)"
|
echo "bitcoin-rpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-public)"
|
||||||
${optionalString (cfg.getPublicAddressCmd != "") ''
|
${optionalString (cfg.getPublicAddressCmd != "") ''
|
||||||
echo "announce-addr=$(${cfg.getPublicAddressCmd})"
|
echo "announce-addr=$(${cfg.getPublicAddressCmd})"
|
||||||
''}
|
''}
|
||||||
} >> '${cfg.dataDir}/config'
|
} >> '${cfg.dataDir}/config'
|
||||||
|
'';
|
||||||
'';
|
|
||||||
serviceConfig = nbLib.defaultHardening // {
|
serviceConfig = nbLib.defaultHardening // {
|
||||||
ExecStart = "${nbPkgs.clightning}/bin/lightningd --lightning-dir=${cfg.dataDir}";
|
ExecStart = "${nbPkgs.clightning}/bin/lightningd --lightning-dir=${cfg.dataDir}";
|
||||||
User = "${cfg.user}";
|
User = cfg.user;
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = "10s";
|
RestartSec = "10s";
|
||||||
ReadWritePaths = "${cfg.dataDir}";
|
ReadWritePaths = cfg.dataDir;
|
||||||
} // (if cfg.enforceTor
|
} // (if cfg.enforceTor
|
||||||
then nbLib.allowTor
|
then nbLib.allowTor
|
||||||
else nbLib.allowAnyIP
|
else nbLib.allowAnyIP
|
||||||
@ -154,5 +141,12 @@ in {
|
|||||||
chmod g+x ${cfg.networkDir}
|
chmod g+x ${cfg.networkDir}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
users.users.${cfg.user} = {
|
||||||
|
group = cfg.group;
|
||||||
|
extraGroups = [ "bitcoinrpc" ];
|
||||||
|
};
|
||||||
|
users.groups.${cfg.group} = {};
|
||||||
|
nix-bitcoin.operator.groups = [ cfg.group ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,6 @@ in {
|
|||||||
];
|
];
|
||||||
|
|
||||||
systemd.services.electrs = {
|
systemd.services.electrs = {
|
||||||
description = "Electrs Electrum Server";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
requires = [ "bitcoind.service" ];
|
requires = [ "bitcoind.service" ];
|
||||||
after = [ "bitcoind.service" ];
|
after = [ "bitcoind.service" ];
|
||||||
@ -110,7 +109,6 @@ in {
|
|||||||
};
|
};
|
||||||
|
|
||||||
users.users.${cfg.user} = {
|
users.users.${cfg.user} = {
|
||||||
description = "electrs User";
|
|
||||||
group = cfg.group;
|
group = cfg.group;
|
||||||
extraGroups = [ "bitcoinrpc" ] ++ optionals cfg.high-memory [ "bitcoin" ];
|
extraGroups = [ "bitcoinrpc" ] ++ optionals cfg.high-memory [ "bitcoin" ];
|
||||||
};
|
};
|
||||||
|
@ -47,11 +47,12 @@ in {
|
|||||||
# Provides lsusb for debugging
|
# Provides lsusb for debugging
|
||||||
pkgs.usbutils
|
pkgs.usbutils
|
||||||
];
|
];
|
||||||
users.groups."${cfg.group}" = {};
|
|
||||||
|
users.groups.${cfg.group} = {};
|
||||||
nix-bitcoin.operator.groups = [ cfg.group ];
|
nix-bitcoin.operator.groups = [ cfg.group ];
|
||||||
})
|
})
|
||||||
(mkIf cfg.ledger {
|
|
||||||
|
|
||||||
|
(mkIf cfg.ledger {
|
||||||
# Ledger Nano S according to https://github.com/LedgerHQ/udev-rules/blob/master/add_udev_rules.sh
|
# Ledger Nano S according to https://github.com/LedgerHQ/udev-rules/blob/master/add_udev_rules.sh
|
||||||
# Don't use rules from nixpkgs because we want to use our own group.
|
# Don't use rules from nixpkgs because we want to use our own group.
|
||||||
services.udev.packages = lib.singleton (pkgs.writeTextFile {
|
services.udev.packages = lib.singleton (pkgs.writeTextFile {
|
||||||
|
@ -46,16 +46,6 @@ in {
|
|||||||
default = "/var/lib/joinmarket-ob-watcher";
|
default = "/var/lib/joinmarket-ob-watcher";
|
||||||
description = "The data directory for JoinMarket orderbook watcher.";
|
description = "The data directory for JoinMarket orderbook watcher.";
|
||||||
};
|
};
|
||||||
user = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "joinmarket-ob-watcher";
|
|
||||||
description = "The user as which to run JoinMarket orderbook watcher.";
|
|
||||||
};
|
|
||||||
group = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = cfg.user;
|
|
||||||
description = "The group as which to run JoinMarket orderbook watcher.";
|
|
||||||
};
|
|
||||||
# This option is only used by netns-isolation
|
# This option is only used by netns-isolation
|
||||||
enforceTor = mkOption {
|
enforceTor = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
@ -64,6 +54,7 @@ in {
|
|||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
# Joinmarket is Tor-only
|
||||||
services.tor = {
|
services.tor = {
|
||||||
enable = true;
|
enable = true;
|
||||||
client.enable = true;
|
client.enable = true;
|
||||||
@ -73,27 +64,23 @@ in {
|
|||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
requires = [ "tor.service" ];
|
requires = [ "tor.service" ];
|
||||||
after = [ "tor.service" ];
|
after = [ "tor.service" ];
|
||||||
|
# The service writes to HOME/.config/matplotlib
|
||||||
|
environment.HOME = cfg.dataDir;
|
||||||
preStart = ''
|
preStart = ''
|
||||||
ln -snf ${configFile} ${cfg.dataDir}/joinmarket.cfg
|
ln -snf ${configFile} ${cfg.dataDir}/joinmarket.cfg
|
||||||
'';
|
'';
|
||||||
serviceConfig = nbLib.defaultHardening // rec {
|
serviceConfig = nbLib.defaultHardening // rec {
|
||||||
|
DynamicUser = true;
|
||||||
StateDirectory = "joinmarket-ob-watcher";
|
StateDirectory = "joinmarket-ob-watcher";
|
||||||
StateDirectoryMode = "0770";
|
StateDirectoryMode = "0770";
|
||||||
WorkingDirectory = "${cfg.dataDir}"; # The service creates dir 'logs' in the working dir
|
WorkingDirectory = cfg.dataDir; # The service creates dir 'logs' in the working dir
|
||||||
ExecStart = ''
|
ExecStart = ''
|
||||||
${nbPkgs.joinmarket}/bin/ob-watcher --datadir=${cfg.dataDir} \
|
${nbPkgs.joinmarket}/bin/ob-watcher --datadir=${cfg.dataDir} \
|
||||||
--host=${cfg.address} --port=${toString cfg.port}
|
--host=${cfg.address} --port=${toString cfg.port}
|
||||||
'';
|
'';
|
||||||
User = cfg.user;
|
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = "10s";
|
RestartSec = "10s";
|
||||||
} // nbLib.allowTor;
|
} // nbLib.allowTor;
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users.${cfg.user} = {
|
|
||||||
group = cfg.group;
|
|
||||||
home = cfg.dataDir; # The service writes to HOME/.config/matplotlib
|
|
||||||
};
|
|
||||||
users.groups.${cfg.group} = {};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -141,75 +141,79 @@ in {
|
|||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable (mkMerge [{
|
config = mkIf cfg.enable (mkMerge [{
|
||||||
services.bitcoind.enable = true;
|
services.bitcoind = {
|
||||||
|
enable = true;
|
||||||
|
disablewallet = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Joinmarket is Tor-only
|
||||||
|
services.tor = {
|
||||||
|
enable = true;
|
||||||
|
client.enable = true;
|
||||||
|
# Needed for payjoin onion service creation
|
||||||
|
controlSocket.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
(hiPrio cfg.cli)
|
(hiPrio cfg.cli)
|
||||||
];
|
];
|
||||||
users.users.${cfg.user} = {
|
|
||||||
description = "joinmarket User";
|
|
||||||
group = "${cfg.group}";
|
|
||||||
home = cfg.dataDir;
|
|
||||||
extraGroups = [ "tor" ];
|
|
||||||
};
|
|
||||||
users.groups.${cfg.group} = {};
|
|
||||||
nix-bitcoin.operator = {
|
|
||||||
groups = [ cfg.group ];
|
|
||||||
sudoUsers = [ cfg.group ];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
systemd.tmpfiles.rules = [
|
||||||
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
|
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
|
||||||
];
|
];
|
||||||
|
|
||||||
services.bitcoind.disablewallet = false;
|
|
||||||
|
|
||||||
# Joinmarket is TOR-only
|
|
||||||
services.tor = {
|
|
||||||
enable = true;
|
|
||||||
client.enable = true;
|
|
||||||
controlSocket.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.joinmarket = {
|
systemd.services.joinmarket = {
|
||||||
description = "JoinMarket Daemon";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
requires = [ "bitcoind.service" ];
|
requires = [ "bitcoind.service" ];
|
||||||
after = [ "bitcoind.service" ];
|
after = [ "bitcoind.service" ];
|
||||||
path = [ pkgs.sudo ];
|
path = [ pkgs.sudo ];
|
||||||
serviceConfig = nbLib.defaultHardening // {
|
serviceConfig = nbLib.defaultHardening // {
|
||||||
ExecStartPre = nbLib.privileged ''
|
ExecStartPre = nbLib.privileged "joinmarket-create-config" ''
|
||||||
install -o '${cfg.user}' -g '${cfg.group}' -m 640 ${configFile} ${cfg.dataDir}/joinmarket.cfg
|
install -o '${cfg.user}' -g '${cfg.group}' -m 640 ${configFile} ${cfg.dataDir}/joinmarket.cfg
|
||||||
sed -i \
|
sed -i \
|
||||||
"s|@@RPC_PASSWORD@@|rpc_password = $(cat ${secretsDir}/bitcoin-rpcpassword-privileged)|" \
|
"s|@@RPC_PASSWORD@@|rpc_password = $(cat ${secretsDir}/bitcoin-rpcpassword-privileged)|" \
|
||||||
'${cfg.dataDir}/joinmarket.cfg'
|
'${cfg.dataDir}/joinmarket.cfg'
|
||||||
'';
|
'';
|
||||||
# Generating wallets (jmclient/wallet.py) is only supported for mainnet or testnet
|
# Generating wallets (jmclient/wallet.py) is only supported for mainnet or testnet
|
||||||
ExecStartPost = mkIf (bitcoind.network == "mainnet") (nbLib.privileged ''
|
ExecStartPost = mkIf (bitcoind.network == "mainnet")
|
||||||
walletname=wallet.jmdat
|
(nbLib.privileged "joinmarket-create-wallet" ''
|
||||||
pw=$(cat "${secretsDir}"/jm-wallet-password)
|
walletname=wallet.jmdat
|
||||||
mnemonic=${secretsDir}/jm-wallet-seed
|
wallet=${cfg.dataDir}/wallets/$walletname
|
||||||
if [[ ! -f ${cfg.dataDir}/wallets/$walletname ]]; then
|
if [[ ! -f $wallet ]]; then
|
||||||
echo Create joinmarket wallet
|
echo "Create wallet"
|
||||||
# Use bash variables so commands don't proceed on previous failures
|
pw=$(cat "${secretsDir}"/jm-wallet-password)
|
||||||
# (like with pipes)
|
cd ${cfg.dataDir}
|
||||||
cd ${cfg.dataDir} && \
|
if ! sudo -u ${cfg.user} ${nbPkgs.joinmarket}/bin/jm-genwallet --datadir=${cfg.dataDir} $walletname $pw \
|
||||||
out=$(sudo -u ${cfg.user} \
|
| grep 'recovery_seed' \
|
||||||
${nbPkgs.joinmarket}/bin/jm-genwallet \
|
| cut -d ':' -f2 \
|
||||||
--datadir=${cfg.dataDir} $walletname $pw)
|
| (umask u=r,go=; cat > "${secretsDir}/jm-wallet-seed"); then
|
||||||
recoveryseed=$(echo "$out" | grep 'recovery_seed')
|
echo "wallet creation failed"
|
||||||
echo "$recoveryseed" | cut -d ':' -f2 > $mnemonic
|
rm -f "$wallet" "${secretsDir}/jm-wallet-seed"
|
||||||
fi
|
exit 1
|
||||||
'');
|
fi
|
||||||
|
fi
|
||||||
|
'');
|
||||||
ExecStart = "${nbPkgs.joinmarket}/bin/joinmarketd";
|
ExecStart = "${nbPkgs.joinmarket}/bin/joinmarketd";
|
||||||
WorkingDirectory = "${cfg.dataDir}"; # The service creates 'commitmentlist' in the working dir
|
WorkingDirectory = cfg.dataDir; # The service creates 'commitmentlist' in the working dir
|
||||||
User = "${cfg.user}";
|
User = cfg.user;
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = "10s";
|
RestartSec = "10s";
|
||||||
ReadWritePaths = "${cfg.dataDir}";
|
ReadWritePaths = cfg.dataDir;
|
||||||
} // nbLib.allowTor;
|
} // nbLib.allowTor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
users.users.${cfg.user} = {
|
||||||
|
group = cfg.group;
|
||||||
|
home = cfg.dataDir;
|
||||||
|
# Allow access to the tor control socket, needed for payjoin onion service creation
|
||||||
|
extraGroups = [ "tor" ];
|
||||||
|
};
|
||||||
|
users.groups.${cfg.group} = {};
|
||||||
|
nix-bitcoin.operator = {
|
||||||
|
groups = [ cfg.group ];
|
||||||
|
sudoUsers = [ cfg.group ];
|
||||||
|
};
|
||||||
|
|
||||||
nix-bitcoin.secrets.jm-wallet-password.user = cfg.user;
|
nix-bitcoin.secrets.jm-wallet-password.user = cfg.user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,7 +231,6 @@ in {
|
|||||||
chmod +x $out
|
chmod +x $out
|
||||||
'';
|
'';
|
||||||
in {
|
in {
|
||||||
description = "CoinJoin maker bot to gain privacy and passively generate income";
|
|
||||||
wantedBy = [ "joinmarket.service" ];
|
wantedBy = [ "joinmarket.service" ];
|
||||||
requires = [ "joinmarket.service" ];
|
requires = [ "joinmarket.service" ];
|
||||||
after = [ "joinmarket.service" ];
|
after = [ "joinmarket.service" ];
|
||||||
@ -242,10 +245,14 @@ in {
|
|||||||
serviceConfig = nbLib.defaultHardening // rec {
|
serviceConfig = nbLib.defaultHardening // rec {
|
||||||
RuntimeDirectory = "joinmarket-yieldgenerator"; # Only used to create start script
|
RuntimeDirectory = "joinmarket-yieldgenerator"; # Only used to create start script
|
||||||
RuntimeDirectoryMode = "700";
|
RuntimeDirectoryMode = "700";
|
||||||
WorkingDirectory = "${cfg.dataDir}"; # The service creates dir 'logs' in the working dir
|
WorkingDirectory = cfg.dataDir; # The service creates dir 'logs' in the working dir
|
||||||
ExecStart = "${pkgs.bash}/bin/bash /run/${RuntimeDirectory}/start";
|
ExecStart = "${pkgs.bash}/bin/bash /run/${RuntimeDirectory}/start";
|
||||||
User = "${cfg.user}";
|
# Show "joinmarket-yieldgenerator" instead of "bash" in the journal.
|
||||||
ReadWritePaths = "${cfg.dataDir}";
|
# The parent bash start process has to run alongside the main process
|
||||||
|
# because it provides the wallet password via stdin to the main process
|
||||||
|
SyslogIdentifier = "joinmarket-yieldgenerator";
|
||||||
|
User = cfg.user;
|
||||||
|
ReadWritePaths = cfg.dataDir;
|
||||||
} // nbLib.allowTor;
|
} // nbLib.allowTor;
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
@ -101,7 +101,7 @@ in {
|
|||||||
User = "lnd";
|
User = "lnd";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = "10s";
|
RestartSec = "10s";
|
||||||
ReadWritePaths = "${cfg.dataDir}";
|
ReadWritePaths = cfg.dataDir;
|
||||||
} // (if cfg.enforceTor
|
} // (if cfg.enforceTor
|
||||||
then nbLib.allowTor
|
then nbLib.allowTor
|
||||||
else nbLib.allowAnyIP);
|
else nbLib.allowAnyIP);
|
||||||
|
@ -87,9 +87,8 @@ in {
|
|||||||
par=16
|
par=16
|
||||||
rpcthreads=16
|
rpcthreads=16
|
||||||
logips=1
|
logips=1
|
||||||
|
|
||||||
'';
|
'';
|
||||||
description = "Additional configurations to be appended to <filename>elements.conf</filename>.";
|
description = "Extra lines appended to <filename>elements.conf</filename>.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
@ -123,7 +122,7 @@ in {
|
|||||||
alice.passwordHMAC = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
|
alice.passwordHMAC = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
|
||||||
bob.passwordHMAC = "b2dd077cb54591a2f3139e69a897ac$4e71f08d48b4347cf8eff3815c0e25ae2e9a4340474079f55705f40574f4ec99";
|
bob.passwordHMAC = "b2dd077cb54591a2f3139e69a897ac$4e71f08d48b4347cf8eff3815c0e25ae2e9a4340474079f55705f40574f4ec99";
|
||||||
};
|
};
|
||||||
type = with types; loaOf (submodule rpcUserOpts);
|
type = with types; attrsOf (submodule rpcUserOpts);
|
||||||
description = ''
|
description = ''
|
||||||
RPC user information for JSON-RPC connections.
|
RPC user information for JSON-RPC connections.
|
||||||
'';
|
'';
|
||||||
@ -221,25 +220,25 @@ in {
|
|||||||
];
|
];
|
||||||
|
|
||||||
systemd.services.liquidd = {
|
systemd.services.liquidd = {
|
||||||
description = "Elements daemon providing access to the Liquid sidechain";
|
|
||||||
requires = [ "bitcoind.service" ];
|
requires = [ "bitcoind.service" ];
|
||||||
after = [ "bitcoind.service" ];
|
after = [ "bitcoind.service" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
preStart = ''
|
preStart = ''
|
||||||
cp '${configFile}' '${cfg.dataDir}/elements.conf'
|
|
||||||
chmod 640 '${cfg.dataDir}/elements.conf'
|
|
||||||
chown -R '${cfg.user}:${cfg.group}' '${cfg.dataDir}'
|
chown -R '${cfg.user}:${cfg.group}' '${cfg.dataDir}'
|
||||||
echo "rpcpassword=$(cat ${secretsDir}/liquid-rpcpassword)" >> '${cfg.dataDir}/elements.conf'
|
install -m 640 ${configFile} '${cfg.dataDir}/elements.conf'
|
||||||
echo "mainchainrpcpassword=$(cat ${secretsDir}/bitcoin-rpcpassword-public)" >> '${cfg.dataDir}/elements.conf'
|
{
|
||||||
|
echo "rpcpassword=$(cat ${secretsDir}/liquid-rpcpassword)"
|
||||||
|
echo "mainchainrpcpassword=$(cat ${secretsDir}/bitcoin-rpcpassword-public)"
|
||||||
|
} >> '${cfg.dataDir}/elements.conf'
|
||||||
'';
|
'';
|
||||||
serviceConfig = nbLib.defaultHardening // {
|
serviceConfig = nbLib.defaultHardening // {
|
||||||
Type = "simple";
|
Type = "simple";
|
||||||
User = "${cfg.user}";
|
User = cfg.user;
|
||||||
Group = "${cfg.group}";
|
Group = cfg.group;
|
||||||
ExecStart = "${nbPkgs.elementsd}/bin/elementsd ${cmdlineOptions}";
|
ExecStart = "${nbPkgs.elementsd}/bin/elementsd ${cmdlineOptions}";
|
||||||
PIDFile = "${pidFile}";
|
PIDFile = pidFile;
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
ReadWritePaths = "${cfg.dataDir}";
|
ReadWritePaths = cfg.dataDir;
|
||||||
} // (if cfg.enforceTor
|
} // (if cfg.enforceTor
|
||||||
then nbLib.allowTor
|
then nbLib.allowTor
|
||||||
else nbLib.allowAnyIP
|
else nbLib.allowAnyIP
|
||||||
@ -249,7 +248,6 @@ in {
|
|||||||
users.users.${cfg.user} = {
|
users.users.${cfg.user} = {
|
||||||
group = cfg.group;
|
group = cfg.group;
|
||||||
extraGroups = [ "bitcoinrpc" ];
|
extraGroups = [ "bitcoinrpc" ];
|
||||||
description = "Liquid sidechain user";
|
|
||||||
};
|
};
|
||||||
users.groups.${cfg.group} = {};
|
users.groups.${cfg.group} = {};
|
||||||
nix-bitcoin.operator.groups = [ cfg.group ];
|
nix-bitcoin.operator.groups = [ cfg.group ];
|
||||||
|
@ -37,13 +37,7 @@ let
|
|||||||
in {
|
in {
|
||||||
|
|
||||||
options.services.lnd = {
|
options.services.lnd = {
|
||||||
enable = mkOption {
|
enable = mkEnableOption "Lightning Network Daemon";
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
If enabled, the LND service will be installed.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/lnd";
|
default = "/var/lib/lnd";
|
||||||
@ -89,7 +83,7 @@ in {
|
|||||||
tor-socks = mkOption {
|
tor-socks = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = if cfg.enforceTor then config.services.tor.client.socksListenAddress else null;
|
default = if cfg.enforceTor then config.services.tor.client.socksListenAddress else null;
|
||||||
description = "Set a socks proxy to use to connect to Tor nodes";
|
description = "Socks proxy for connecting to Tor nodes";
|
||||||
};
|
};
|
||||||
macaroons = mkOption {
|
macaroons = mkOption {
|
||||||
default = {};
|
default = {};
|
||||||
@ -118,7 +112,7 @@ in {
|
|||||||
example = ''
|
example = ''
|
||||||
autopilot.active=1
|
autopilot.active=1
|
||||||
'';
|
'';
|
||||||
description = "Additional configurations to be appended to <filename>lnd.conf</filename>.";
|
description = "Extra lines appended to <filename>lnd.conf</filename>.";
|
||||||
};
|
};
|
||||||
package = mkOption {
|
package = mkOption {
|
||||||
type = types.package;
|
type = types.package;
|
||||||
@ -156,9 +150,13 @@ in {
|
|||||||
|
|
||||||
services.bitcoind = {
|
services.bitcoind = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
# Increase rpc thread count due to reports that lightning implementations fail
|
# Increase rpc thread count due to reports that lightning implementations fail
|
||||||
# under high bitcoind rpc load
|
# under high bitcoind rpc load
|
||||||
rpc.threads = 16;
|
rpc.threads = 16;
|
||||||
|
|
||||||
|
zmqpubrawblock = "tcp://${bitcoindRpcAddress}:28332";
|
||||||
|
zmqpubrawtx = "tcp://${bitcoindRpcAddress}:28333";
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = [ cfg.package (hiPrio cfg.cli) ];
|
environment.systemPackages = [ cfg.package (hiPrio cfg.cli) ];
|
||||||
@ -167,13 +165,7 @@ in {
|
|||||||
"d '${cfg.dataDir}' 0770 lnd lnd - -"
|
"d '${cfg.dataDir}' 0770 lnd lnd - -"
|
||||||
];
|
];
|
||||||
|
|
||||||
services.bitcoind = {
|
|
||||||
zmqpubrawblock = "tcp://${bitcoindRpcAddress}:28332";
|
|
||||||
zmqpubrawtx = "tcp://${bitcoindRpcAddress}:28333";
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.lnd = {
|
systemd.services.lnd = {
|
||||||
description = "Run LND";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
requires = [ "bitcoind.service" ];
|
requires = [ "bitcoind.service" ];
|
||||||
after = [ "bitcoind.service" ];
|
after = [ "bitcoind.service" ];
|
||||||
@ -193,12 +185,12 @@ in {
|
|||||||
User = "lnd";
|
User = "lnd";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = "10s";
|
RestartSec = "10s";
|
||||||
ReadWritePaths = "${cfg.dataDir}";
|
ReadWritePaths = cfg.dataDir;
|
||||||
ExecStartPost = let
|
ExecStartPost = let
|
||||||
restUrl = "https://${cfg.restAddress}:${toString cfg.restPort}/v1";
|
restUrl = "https://${cfg.restAddress}:${toString cfg.restPort}/v1";
|
||||||
in [
|
in [
|
||||||
# Run fully privileged for secrets dir write access
|
# Run fully privileged for secrets dir write access
|
||||||
"+${nbLib.script ''
|
(nbLib.privileged "lnd-create-mnemonic" ''
|
||||||
attempts=250
|
attempts=250
|
||||||
while ! { exec 3>/dev/tcp/${cfg.restAddress}/${toString cfg.restPort} && exec 3>&-; } &>/dev/null; do
|
while ! { exec 3>/dev/tcp/${cfg.restAddress}/${toString cfg.restPort} && exec 3>&-; } &>/dev/null; do
|
||||||
((attempts-- == 0)) && { echo "lnd REST service unreachable"; exit 1; }
|
((attempts-- == 0)) && { echo "lnd REST service unreachable"; exit 1; }
|
||||||
@ -214,8 +206,8 @@ in {
|
|||||||
-X GET ${restUrl}/genseed | ${pkgs.jq}/bin/jq -c '.cipher_seed_mnemonic' > "$mnemonic"
|
-X GET ${restUrl}/genseed | ${pkgs.jq}/bin/jq -c '.cipher_seed_mnemonic' > "$mnemonic"
|
||||||
fi
|
fi
|
||||||
chown lnd: "$mnemonic"
|
chown lnd: "$mnemonic"
|
||||||
''}"
|
'')
|
||||||
"${nbLib.script ''
|
(nbLib.script "lnd-create-wallet" ''
|
||||||
if [[ ! -f ${networkDir}/wallet.db ]]; then
|
if [[ ! -f ${networkDir}/wallet.db ]]; then
|
||||||
echo Create lnd wallet
|
echo Create lnd wallet
|
||||||
|
|
||||||
@ -246,9 +238,9 @@ in {
|
|||||||
sleep 0.1
|
sleep 0.1
|
||||||
done
|
done
|
||||||
|
|
||||||
''}"
|
'')
|
||||||
# Run fully privileged for chown
|
# Run fully privileged for chown
|
||||||
"+${nbLib.script ''
|
(nbLib.privileged "lnd-create-macaroons" ''
|
||||||
umask ug=r,o=
|
umask ug=r,o=
|
||||||
${lib.concatMapStrings (macaroon: ''
|
${lib.concatMapStrings (macaroon: ''
|
||||||
echo "Create custom macaroon ${macaroon}"
|
echo "Create custom macaroon ${macaroon}"
|
||||||
@ -262,7 +254,7 @@ in {
|
|||||||
${pkgs.jq}/bin/jq -c '.macaroon' | ${pkgs.xxd}/bin/xxd -p -r > "$macaroonPath"
|
${pkgs.jq}/bin/jq -c '.macaroon' | ${pkgs.xxd}/bin/xxd -p -r > "$macaroonPath"
|
||||||
chown ${cfg.macaroons.${macaroon}.user}: "$macaroonPath"
|
chown ${cfg.macaroons.${macaroon}.user}: "$macaroonPath"
|
||||||
'') (attrNames cfg.macaroons)}
|
'') (attrNames cfg.macaroons)}
|
||||||
''}"
|
'')
|
||||||
];
|
];
|
||||||
} // (if cfg.enforceTor
|
} // (if cfg.enforceTor
|
||||||
then nbLib.allowTor
|
then nbLib.allowTor
|
||||||
@ -271,7 +263,6 @@ in {
|
|||||||
};
|
};
|
||||||
|
|
||||||
users.users.lnd = {
|
users.users.lnd = {
|
||||||
description = "LND User";
|
|
||||||
group = "lnd";
|
group = "lnd";
|
||||||
extraGroups = [ "bitcoinrpc" ];
|
extraGroups = [ "bitcoinrpc" ];
|
||||||
home = cfg.dataDir; # lnd creates .lnd dir in HOME
|
home = cfg.dataDir; # lnd creates .lnd dir in HOME
|
||||||
|
@ -105,7 +105,7 @@ in {
|
|||||||
source = config.nix-bitcoin.pkgs.netns-exec;
|
source = config.nix-bitcoin.pkgs.netns-exec;
|
||||||
capabilities = "cap_sys_admin=ep";
|
capabilities = "cap_sys_admin=ep";
|
||||||
owner = cfg.allowedUser;
|
owner = cfg.allowedUser;
|
||||||
permissions = "u+rx,g+rx,o-rwx";
|
permissions = "550";
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services = {
|
systemd.services = {
|
||||||
@ -119,7 +119,7 @@ in {
|
|||||||
after = [ "network-pre.target" ];
|
after = [ "network-pre.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = "yes";
|
RemainAfterExit = true;
|
||||||
};
|
};
|
||||||
script = ''
|
script = ''
|
||||||
${ip} link add name nb-br type bridge
|
${ip} link add name nb-br type bridge
|
||||||
@ -182,7 +182,7 @@ in {
|
|||||||
'';
|
'';
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = "yes";
|
RemainAfterExit = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -41,13 +41,7 @@ let
|
|||||||
'';
|
'';
|
||||||
in {
|
in {
|
||||||
options.services.recurring-donations = {
|
options.services.recurring-donations = {
|
||||||
enable = mkOption {
|
enable = mkEnableOption "recurring-donations";
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
If enabled, the recurring-donations service will be installed.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
tallycoin = mkOption {
|
tallycoin = mkOption {
|
||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
default = {};
|
default = {};
|
||||||
@ -81,15 +75,7 @@ in {
|
|||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
services.clightning.enable = true;
|
services.clightning.enable = true;
|
||||||
|
|
||||||
users.users.recurring-donations = {
|
|
||||||
description = "recurring-donations User";
|
|
||||||
group = "recurring-donations";
|
|
||||||
extraGroups = [ "clightning" ];
|
|
||||||
};
|
|
||||||
users.groups.recurring-donations = {};
|
|
||||||
|
|
||||||
systemd.services.recurring-donations = {
|
systemd.services.recurring-donations = {
|
||||||
description = "Run recurring-donations";
|
|
||||||
requires = [ "clightning.service" ];
|
requires = [ "clightning.service" ];
|
||||||
after = [ "clightning.service" ];
|
after = [ "clightning.service" ];
|
||||||
path = with pkgs; [ nix-bitcoin.clightning curl sudo jq ];
|
path = with pkgs; [ nix-bitcoin.clightning curl sudo jq ];
|
||||||
@ -111,5 +97,11 @@ in {
|
|||||||
};
|
};
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
users.users.recurring-donations = {
|
||||||
|
group = "recurring-donations";
|
||||||
|
extraGroups = [ "clightning" ];
|
||||||
|
};
|
||||||
|
users.groups.recurring-donations = {};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -23,13 +23,7 @@ let
|
|||||||
'';
|
'';
|
||||||
in {
|
in {
|
||||||
options.services.spark-wallet = {
|
options.services.spark-wallet = {
|
||||||
enable = mkOption {
|
enable = mkEnableOption "spark-wallet";
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
If enabled, the spark-wallet service will be installed.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "localhost";
|
default = "localhost";
|
||||||
@ -61,14 +55,12 @@ in {
|
|||||||
services.clightning.enable = true;
|
services.clightning.enable = true;
|
||||||
|
|
||||||
users.users.spark-wallet = {
|
users.users.spark-wallet = {
|
||||||
description = "spark-wallet User";
|
|
||||||
group = "spark-wallet";
|
group = "spark-wallet";
|
||||||
extraGroups = [ "clightning" ];
|
extraGroups = [ "clightning" ];
|
||||||
};
|
};
|
||||||
users.groups.spark-wallet = {};
|
users.groups.spark-wallet = {};
|
||||||
|
|
||||||
systemd.services.spark-wallet = {
|
systemd.services.spark-wallet = {
|
||||||
description = "Run spark-wallet";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
requires = [ "clightning.service" ];
|
requires = [ "clightning.service" ];
|
||||||
after = [ "clightning.service" ];
|
after = [ "clightning.service" ];
|
||||||
|
@ -3,20 +3,20 @@
|
|||||||
, withGui }:
|
, withGui }:
|
||||||
|
|
||||||
with stdenv.lib;
|
with stdenv.lib;
|
||||||
stdenv.mkDerivation rec{
|
stdenv.mkDerivation rec {
|
||||||
name = "elements" + (toString (optional (!withGui) "d")) + "-" + version;
|
pname = "elements${optionalString (!withGui) "d"}";
|
||||||
version = "0.18.1.9";
|
version = "0.18.1.9";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
urls = [
|
url = "https://github.com/ElementsProject/elements/archive/elements-${version}.tar.gz";
|
||||||
"https://github.com/ElementsProject/elements/archive/elements-${version}.tar.gz"
|
# Use ./get-sha256.sh to fetch latest (verified) sha256
|
||||||
];
|
|
||||||
sha256 = "c6f1b040a896a1aaa7340f5cd48e119c84fef88df5d4c17d5ad5c13783f5b6c7";
|
sha256 = "c6f1b040a896a1aaa7340f5cd48e119c84fef88df5d4c17d5ad5c13783f5b6c7";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs =
|
nativeBuildInputs =
|
||||||
[ pkgconfig autoreconfHook ]
|
[ pkgconfig autoreconfHook ]
|
||||||
++ optional withGui wrapQtAppsHook;
|
++ optional withGui wrapQtAppsHook;
|
||||||
|
|
||||||
buildInputs = [ openssl db48 boost zlib zeromq
|
buildInputs = [ openssl db48 boost zlib zeromq
|
||||||
miniupnpc protobuf libevent]
|
miniupnpc protobuf libevent]
|
||||||
++ optionals stdenv.isLinux [ utillinux ]
|
++ optionals stdenv.isLinux [ utillinux ]
|
||||||
@ -27,10 +27,10 @@ stdenv.mkDerivation rec{
|
|||||||
] ++ optionals (!doCheck) [
|
] ++ optionals (!doCheck) [
|
||||||
"--disable-tests"
|
"--disable-tests"
|
||||||
"--disable-gui-tests"
|
"--disable-gui-tests"
|
||||||
]
|
] ++ optionals withGui [
|
||||||
++ optionals withGui [ "--with-gui=qt5"
|
"--with-gui=qt5"
|
||||||
"--with-qt-bindir=${qtbase.dev}/bin:${qttools.dev}/bin"
|
"--with-qt-bindir=${qtbase.dev}/bin:${qttools.dev}/bin"
|
||||||
];
|
];
|
||||||
|
|
||||||
checkInputs = [ rapidcheck python3 ];
|
checkInputs = [ rapidcheck python3 ];
|
||||||
|
|
||||||
|
@ -28,8 +28,9 @@ let self = {
|
|||||||
CapabilityBoundingSet = "";
|
CapabilityBoundingSet = "";
|
||||||
# @system-service whitelist and docker seccomp blacklist (except for "clone"
|
# @system-service whitelist and docker seccomp blacklist (except for "clone"
|
||||||
# which is a core requirement for systemd services)
|
# which is a core requirement for systemd services)
|
||||||
|
# @system-service is defined in src/shared/seccomp-util.c (systemd source)
|
||||||
SystemCallFilter = [ "@system-service" "~add_key clone3 get_mempolicy kcmp keyctl mbind move_pages name_to_handle_at personality process_vm_readv process_vm_writev request_key set_mempolicy setns unshare userfaultfd" ];
|
SystemCallFilter = [ "@system-service" "~add_key clone3 get_mempolicy kcmp keyctl mbind move_pages name_to_handle_at personality process_vm_readv process_vm_writev request_key set_mempolicy setns unshare userfaultfd" ];
|
||||||
SystemCallArchitectures= "native";
|
SystemCallArchitectures = "native";
|
||||||
};
|
};
|
||||||
|
|
||||||
# nodejs applications apparently rely on memory write execute
|
# nodejs applications apparently rely on memory write execute
|
||||||
@ -51,13 +52,13 @@ let self = {
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
script = src: pkgs.writers.writeBash "script" ''
|
script = name: src: pkgs.writers.writeBash name ''
|
||||||
set -eo pipefail
|
set -eo pipefail
|
||||||
${src}
|
${src}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# Used for ExecStart*
|
# Used for ExecStart*
|
||||||
privileged = src: "+${self.script src}";
|
privileged = name: src: "+${self.script name src}";
|
||||||
|
|
||||||
cliExec = mkOption {
|
cliExec = mkOption {
|
||||||
# Used by netns-isolation to execute the cli in the service's private netns
|
# Used by netns-isolation to execute the cli in the service's private netns
|
||||||
|
@ -6,7 +6,7 @@ buildPythonPackage rec {
|
|||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "freelan-developers";
|
owner = "freelan-developers";
|
||||||
repo = "chromalog";
|
repo = "chromalog";
|
||||||
rev = "${version}";
|
rev = version;
|
||||||
sha256 = "0pj4s52rgwlvwkzrj85y92c5r9c84pz8gga45jl5spysrv41y9p0";
|
sha256 = "0pj4s52rgwlvwkzrj85y92c5r9c84pz8gga45jl5spysrv41y9p0";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
18
test/lib/copy-src.sh
Normal file
18
test/lib/copy-src.sh
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Re-run run-tests.sh in a snapshot copy of the source.
|
||||||
|
# Maintain /tmp/nix-bitcoin-src as a source cache to minimize copies.
|
||||||
|
|
||||||
|
tmp=$(mktemp -d '/tmp/nix-bitcoin-src.XXXXX')
|
||||||
|
|
||||||
|
# Ignore errors from now on
|
||||||
|
set +e
|
||||||
|
|
||||||
|
# Move source cache if it exists (atomic)
|
||||||
|
mv /tmp/nix-bitcoin-src $tmp/src 2>/dev/null
|
||||||
|
|
||||||
|
rsync -a --delete --exclude='.git*' "$scriptDir/../" $tmp/src && \
|
||||||
|
echo "Copied src" && \
|
||||||
|
_nixBitcoinInCopySrc=1 $tmp/src/test/run-tests.sh "${args[@]}"
|
||||||
|
|
||||||
|
# Set the current src as the source cache (atomic)
|
||||||
|
mv -T $tmp/src /tmp/nix-bitcoin-src 2>/dev/null
|
||||||
|
rm -rf $tmp
|
@ -42,12 +42,20 @@
|
|||||||
# For now, creating NixOS containers requires root permissions.
|
# For now, creating NixOS containers requires root permissions.
|
||||||
# See ./lib/make-container.sh for a complete documentation.
|
# See ./lib/make-container.sh for a complete documentation.
|
||||||
#
|
#
|
||||||
|
# Run tests from a snapshot copy of the source files
|
||||||
|
# ./run-tests.sh --copy-src|-c ...
|
||||||
|
#
|
||||||
|
# This allows you to continue editing the nix-bitcoin sources while tests are running
|
||||||
|
# and reading source files.
|
||||||
|
# Files are copied to /tmp, a caching scheme helps minimizing copies.
|
||||||
|
#
|
||||||
# To add custom scenarios, set the environment variable `scenarioOverridesFile`.
|
# To add custom scenarios, set the environment variable `scenarioOverridesFile`.
|
||||||
|
|
||||||
set -eo pipefail
|
set -eo pipefail
|
||||||
|
|
||||||
scriptDir=$(cd "${BASH_SOURCE[0]%/*}" && pwd)
|
scriptDir=$(cd "${BASH_SOURCE[0]%/*}" && pwd)
|
||||||
|
|
||||||
|
args=("$@")
|
||||||
scenario=
|
scenario=
|
||||||
outLinkPrefix=
|
outLinkPrefix=
|
||||||
ciBuild=
|
ciBuild=
|
||||||
@ -77,6 +85,13 @@ while :; do
|
|||||||
shift
|
shift
|
||||||
ciBuild=1
|
ciBuild=1
|
||||||
;;
|
;;
|
||||||
|
--copy-src|-c)
|
||||||
|
shift
|
||||||
|
if [[ ! $_nixBitcoinInCopySrc ]]; then
|
||||||
|
. "$scriptDir/lib/copy-src.sh"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
break
|
break
|
||||||
esac
|
esac
|
||||||
@ -172,7 +187,7 @@ doBuild() {
|
|||||||
|
|
||||||
# Run the test by building the test derivation
|
# Run the test by building the test derivation
|
||||||
buildTest() {
|
buildTest() {
|
||||||
vmTestNixExpr | doBuild $scenario $outLinkArg "$@" -
|
vmTestNixExpr | doBuild $scenario "$@" -
|
||||||
}
|
}
|
||||||
|
|
||||||
vmTestNixExpr() {
|
vmTestNixExpr() {
|
||||||
|
Loading…
Reference in New Issue
Block a user