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
|
||||
---
|
||||
See the [examples directory](examples/README.md).
|
||||
See [here for examples](examples/README.md).
|
||||
|
||||
Features
|
||||
---
|
||||
@ -76,7 +76,7 @@ NixOS modules
|
||||
* Helper
|
||||
* [netns-isolation](modules/netns-isolation.nix): isolates applications on the network-level via network namespaces
|
||||
* [nodeinfo](modules/nodeinfo.nix): script which prints info about the node's services
|
||||
* [backups](modules/backups.nix): daily duplicity backups of all your node's important files
|
||||
* [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`)
|
||||
|
||||
Security
|
||||
|
@ -11,18 +11,8 @@ cachixCache=nix-bitcoin
|
||||
|
||||
trap 'echo Error at line $LINENO' ERR
|
||||
|
||||
atExit() {
|
||||
rm -rf $tmpDir
|
||||
if [[ -v cachixPid ]]; then stopCachix; fi
|
||||
}
|
||||
tmpDir=$(mktemp -d -p /tmp)
|
||||
trap atExit EXIT
|
||||
|
||||
stopCachix() {
|
||||
kill $cachixPid 2>/dev/null || true
|
||||
# Wait for cachix to finish
|
||||
tail --pid=$cachixPid -f /dev/null
|
||||
}
|
||||
trap "rm -rf $tmpDir" EXIT
|
||||
|
||||
## Instantiate
|
||||
|
||||
@ -43,14 +33,14 @@ fi
|
||||
|
||||
if [[ $CACHIX_SIGNING_KEY ]]; then
|
||||
# Speed up task by uploading store paths as soon as they are created
|
||||
cachix push $cachixCache --watch-store &
|
||||
cachixPid=$!
|
||||
buildCmd="cachix watch-exec $cachixCache nix-build --"
|
||||
else
|
||||
buildCmd=nix-build
|
||||
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
|
||||
stopCachix
|
||||
cachix push $cachixCache $outPath
|
||||
fi
|
||||
|
||||
|
@ -5,8 +5,8 @@ set -euo pipefail
|
||||
# Running this script leaves no traces on your host system.
|
||||
|
||||
# This demo is a template for your own experiments.
|
||||
# Feel free to modify or to run nix-shell and execute individual statements of this
|
||||
# script in the interactive shell.
|
||||
# Run with option `--interactive` or `-i` to start a shell for interacting with
|
||||
# the node.
|
||||
|
||||
if [[ ! -v IN_NIX_SHELL ]]; then
|
||||
echo "Running script in nix shell env..."
|
||||
|
@ -5,8 +5,8 @@ set -euo pipefail
|
||||
# Running this script leaves no traces on your host system.
|
||||
|
||||
# This demo is a template for your own experiments.
|
||||
# Feel free to modify or to run nix-shell and execute individual statements of this
|
||||
# script in the interactive shell.
|
||||
# Run with option `--interactive` or `-i` to start a shell for interacting with
|
||||
# the node.
|
||||
|
||||
if [[ ! -v IN_NIX_SHELL ]]; then
|
||||
echo "Running script in nix shell env..."
|
||||
|
@ -5,8 +5,8 @@ set -euo pipefail
|
||||
# Running this script leaves no traces on your host system.
|
||||
|
||||
# This demo is a template for your own experiments.
|
||||
# Feel free to modify or to run nix-shell and execute individual statements of this
|
||||
# script in the interactive shell.
|
||||
# Run with option `--interactive` or `-i` to start a shell for interacting with
|
||||
# the node.
|
||||
|
||||
# MAKE SURE TO REPLACE the SSH identity file if you use this script for
|
||||
# anything serious.
|
||||
|
@ -4,13 +4,15 @@ with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.backups;
|
||||
secretsDir = config.nix-bitcoin.secretsDir;
|
||||
|
||||
filelist = pkgs.writeText "filelist.txt" ''
|
||||
${optionalString (!cfg.with-bulk-data) "- ${config.services.bitcoind.dataDir}/blocks"}
|
||||
${optionalString (!cfg.with-bulk-data) "- ${config.services.bitcoind.dataDir}/chainstate"}
|
||||
${config.services.bitcoind.dataDir}
|
||||
${config.services.clightning.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}/*/chainstate"}
|
||||
${config.services.liquidd.dataDir}
|
||||
@ -18,7 +20,7 @@ let
|
||||
${config.services.nbxplorer.dataDir}
|
||||
${config.services.btcpayserver.dataDir}
|
||||
${config.services.joinmarket.dataDir}
|
||||
/secrets/jm-wallet-seed
|
||||
${secretsDir}/jm-wallet-seed
|
||||
${config.services.postgresqlBackup.location}/btcpaydb.sql.gz
|
||||
/var/lib/tor
|
||||
# Extra files
|
||||
@ -27,7 +29,6 @@ let
|
||||
# Exclude all unspecified files and directories
|
||||
- /
|
||||
'';
|
||||
|
||||
in {
|
||||
options.services.backups = {
|
||||
enable = mkEnableOption "Backups service";
|
||||
@ -72,7 +73,7 @@ in {
|
||||
"--include-filelist" "${filelist}"
|
||||
"--full-if-older-than" "1M"
|
||||
];
|
||||
targetUrl = "${cfg.destination}";
|
||||
targetUrl = cfg.destination;
|
||||
frequency = cfg.frequency;
|
||||
secretFile = "${config.nix-bitcoin.secretsDir}/backup-encryption-env";
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ let
|
||||
nbLib = config.nix-bitcoin.lib;
|
||||
secretsDir = config.nix-bitcoin.secretsDir;
|
||||
|
||||
configFile = pkgs.writeText "bitcoin.conf" ''
|
||||
configFile = builtins.toFile "bitcoin.conf" ''
|
||||
# We're already logging via journald
|
||||
nodebuglogfile=1
|
||||
|
||||
@ -90,7 +90,7 @@ in {
|
||||
par=16
|
||||
logips=1
|
||||
'';
|
||||
description = "Additional configurations to be appended to <filename>bitcoin.conf</filename>.";
|
||||
description = "Extra lines appended to <filename>bitcoin.conf</filename>.";
|
||||
};
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
@ -138,7 +138,7 @@ in {
|
||||
alice.passwordHMAC = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
|
||||
bob.passwordHMAC = "b2dd077cb54591a2f3139e69a897ac$4e71f08d48b4347cf8eff3815c0e25ae2e9a4340474079f55705f40574f4ec99";
|
||||
};
|
||||
type = with types; loaOf (submodule ({ name, ... }: {
|
||||
type = with types; attrsOf (submodule ({ name, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
@ -197,9 +197,7 @@ in {
|
||||
listen = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If enabled, the bitcoin service will listen.
|
||||
'';
|
||||
description = "Accept incoming connections.";
|
||||
};
|
||||
dataDirReadableByGroup = mkOption {
|
||||
type = types.bool;
|
||||
@ -228,21 +226,15 @@ in {
|
||||
type = types.nullOr (types.ints.between 4 16384);
|
||||
default = null;
|
||||
example = 4000;
|
||||
description = "Override the default database cache size in megabytes.";
|
||||
description = "Override the default database cache size in MiB.";
|
||||
};
|
||||
prune = mkOption {
|
||||
type = types.ints.unsigned;
|
||||
default = 0;
|
||||
example = 10000;
|
||||
description = ''
|
||||
Reduce storage requirements by enabling pruning (deleting) of old
|
||||
blocks. This allows the pruneblockchain RPC to be called to delete
|
||||
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)
|
||||
Automatically prune block files to stay under the specified target size in MiB.
|
||||
Value 0 disables pruning.
|
||||
'';
|
||||
};
|
||||
zmqpubrawblock = mkOption {
|
||||
@ -281,7 +273,7 @@ in {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "bech32";
|
||||
description = "What type of addresses to use";
|
||||
description = "The type of addresses to use";
|
||||
};
|
||||
cli = mkOption {
|
||||
readOnly = true;
|
||||
@ -320,7 +312,6 @@ in {
|
||||
];
|
||||
|
||||
systemd.services.bitcoind = {
|
||||
description = "Bitcoin daemon";
|
||||
requires = [ "nix-bitcoin-secrets.target" ];
|
||||
after = [ "network.target" "nix-bitcoin-secrets.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
@ -334,10 +325,10 @@ in {
|
||||
in ''
|
||||
${optionalString cfg.dataDirReadableByGroup "chmod -R g+rX '${cfg.dataDir}/blocks'"}
|
||||
cfg=$(
|
||||
cat ${configFile};
|
||||
cat ${configFile}
|
||||
${extraRpcauth}
|
||||
${/* 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
|
||||
${optionalString (cfg.getPublicAddressCmd != "") ''
|
||||
echo "externalip=$(${cfg.getPublicAddressCmd})"
|
||||
@ -351,13 +342,13 @@ in {
|
||||
serviceConfig = nbLib.defaultHardening // {
|
||||
Type = "notify";
|
||||
NotifyAccess = "all";
|
||||
User = "${cfg.user}";
|
||||
Group = "${cfg.group}";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
TimeoutStartSec = 300;
|
||||
ExecStart = "${cfg.package}/bin/bitcoind -datadir='${cfg.dataDir}'";
|
||||
Restart = "on-failure";
|
||||
UMask = mkIf cfg.dataDirReadableByGroup "0027";
|
||||
ReadWritePaths = "${cfg.dataDir}";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // (if cfg.enforceTor
|
||||
then nbLib.allowTor
|
||||
else nbLib.allowAnyIP)
|
||||
@ -383,16 +374,13 @@ in {
|
||||
done
|
||||
'';
|
||||
serviceConfig = nbLib.defaultHardening // {
|
||||
User = "${cfg.user}";
|
||||
Group = "${cfg.group}";
|
||||
ReadWritePaths = "${cfg.dataDir}";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // nbLib.allowTor;
|
||||
};
|
||||
|
||||
users.users.${cfg.user} = {
|
||||
group = cfg.group;
|
||||
description = "Bitcoin daemon user";
|
||||
};
|
||||
users.users.${cfg.user}.group = cfg.group;
|
||||
users.groups.${cfg.group} = {};
|
||||
users.groups.bitcoinrpc = {};
|
||||
nix-bitcoin.operator.groups = [ cfg.group ];
|
||||
|
@ -99,20 +99,34 @@ in {
|
||||
services.clightning.enable = mkIf (cfg.btcpayserver.lightningBackend == "clightning") true;
|
||||
services.lnd.enable = mkIf (cfg.btcpayserver.lightningBackend == "lnd") true;
|
||||
|
||||
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} - -"
|
||||
services.bitcoind.rpc.users.btcpayserver = {
|
||||
passwordHMACFromFile = true;
|
||||
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 = {
|
||||
enable = true;
|
||||
ensureDatabases = [ "btcpaydb" ];
|
||||
ensureUsers = [{
|
||||
name = "${cfg.btcpayserver.user}";
|
||||
name = cfg.btcpayserver.user;
|
||||
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
|
||||
configFile = builtins.toFile "config" ''
|
||||
network=${config.services.bitcoind.network}
|
||||
@ -123,12 +137,11 @@ in {
|
||||
port=${toString cfg.nbxplorer.port}
|
||||
'';
|
||||
in {
|
||||
description = "Run nbxplorer";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "bitcoind.service" ];
|
||||
after = [ "bitcoind.service" ];
|
||||
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)" \
|
||||
>> '${cfg.nbxplorer.dataDir}/settings.config'
|
||||
'';
|
||||
@ -151,13 +164,13 @@ in {
|
||||
systemd.services.btcpayserver = let
|
||||
configFile = builtins.toFile "config" (''
|
||||
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}
|
||||
btcexplorerurl=http://${cfg.nbxplorer.address}:${toString cfg.nbxplorer.port}/
|
||||
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}"}
|
||||
port=${toString cfg.btcpayserver.port}
|
||||
'' + optionalString (cfg.btcpayserver.lightningBackend == "clightning") ''
|
||||
btclightning=type=clightning;server=unix:///${cfg.clightning.dataDir}/bitcoin/lightning-rpc
|
||||
'');
|
||||
@ -168,17 +181,17 @@ in {
|
||||
"certthumbprint=";
|
||||
in let self = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "nbxplorer.service" ]
|
||||
requires = [ "nbxplorer.service" "postgresql.service" ]
|
||||
++ optional (cfg.btcpayserver.lightningBackend != null) "${cfg.btcpayserver.lightningBackend}.service";
|
||||
after = self.requires;
|
||||
preStart = ''
|
||||
install -m 600 ${configFile} ${cfg.btcpayserver.dataDir}/settings.config
|
||||
install -m 600 ${configFile} '${cfg.btcpayserver.dataDir}/settings.config'
|
||||
${optionalString (cfg.btcpayserver.lightningBackend == "lnd") ''
|
||||
{
|
||||
echo -n "${lndConfig}";
|
||||
${pkgs.openssl}/bin/openssl x509 -noout -fingerprint -sha256 -in ${config.nix-bitcoin.secretsDir}/lnd-cert \
|
||||
| sed -e 's/.*=//;s/://g';
|
||||
} >> ${cfg.btcpayserver.dataDir}/settings.config
|
||||
} >> '${cfg.btcpayserver.dataDir}/settings.config'
|
||||
''}
|
||||
'';
|
||||
serviceConfig = nbLib.defaultHardening // {
|
||||
@ -197,20 +210,13 @@ in {
|
||||
);
|
||||
}; 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} = {
|
||||
description = "nbxplorer user";
|
||||
group = cfg.nbxplorer.group;
|
||||
extraGroups = [ "bitcoinrpc" ];
|
||||
home = cfg.nbxplorer.dataDir;
|
||||
};
|
||||
users.groups.${cfg.nbxplorer.group} = {};
|
||||
users.users.${cfg.btcpayserver.user} = {
|
||||
description = "btcpayserver user";
|
||||
group = cfg.btcpayserver.group;
|
||||
extraGroups = [ "nbxplorer" ]
|
||||
++ optional (cfg.btcpayserver.lightningBackend == "clightning") cfg.clightning.user;
|
||||
@ -218,18 +224,12 @@ in {
|
||||
};
|
||||
users.groups.${cfg.btcpayserver.group} = {};
|
||||
|
||||
services.bitcoind.rpc.users.btcpayserver = {
|
||||
passwordHMACFromFile = true;
|
||||
rpcwhitelist = cfg.bitcoind.rpc.users.public.rpcwhitelist ++ [
|
||||
"setban"
|
||||
"generatetoaddress"
|
||||
"getpeerinfo"
|
||||
];
|
||||
};
|
||||
nix-bitcoin.secrets.bitcoin-rpcpassword-btcpayserver = {
|
||||
nix-bitcoin.secrets = {
|
||||
bitcoin-rpcpassword-btcpayserver = {
|
||||
user = "bitcoin";
|
||||
group = "nbxplorer";
|
||||
};
|
||||
nix-bitcoin.secrets.bitcoin-HMAC-btcpayserver.user = "bitcoin";
|
||||
bitcoin-HMAC-btcpayserver.user = "bitcoin";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ let
|
||||
network=${network}
|
||||
bitcoin-datadir=${config.services.bitcoind.dataDir}
|
||||
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
|
||||
always-use-proxy=${if cfg.always-use-proxy then "true" else "false"}
|
||||
always-use-proxy=${boolToString cfg.always-use-proxy}
|
||||
bind-addr=${cfg.address}:${toString cfg.port}
|
||||
bitcoin-rpcconnect=${config.services.bitcoind.rpc.address}
|
||||
bitcoin-rpcport=${toString config.services.bitcoind.rpc.port}
|
||||
@ -21,13 +21,7 @@ let
|
||||
'';
|
||||
in {
|
||||
options.services.clightning = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If enabled, the clightning service will be installed.
|
||||
'';
|
||||
};
|
||||
enable = mkEnableOption "clightning";
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
@ -41,13 +35,17 @@ in {
|
||||
proxy = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
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 {
|
||||
type = types.bool;
|
||||
default = cfg.enforceTor;
|
||||
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 {
|
||||
@ -63,7 +61,7 @@ in {
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = "Additional lines appended to the config file.";
|
||||
description = "Extra lines appended to the configuration file.";
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
@ -77,8 +75,7 @@ in {
|
||||
};
|
||||
cli = mkOption {
|
||||
readOnly = true;
|
||||
default = pkgs.writeScriptBin "lightning-cli"
|
||||
''
|
||||
default = pkgs.writeScriptBin "lightning-cli" ''
|
||||
${nbPkgs.clightning}/bin/lightning-cli --lightning-dir='${cfg.dataDir}' "$@"
|
||||
'';
|
||||
description = "Binary to connect with the clightning instance.";
|
||||
@ -103,44 +100,34 @@ in {
|
||||
};
|
||||
|
||||
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 = [
|
||||
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
|
||||
];
|
||||
|
||||
systemd.services.clightning = {
|
||||
description = "Run clightningd";
|
||||
path = [ nbPkgs.bitcoind ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "bitcoind.service" ];
|
||||
after = [ "bitcoind.service" ];
|
||||
preStart = ''
|
||||
cp ${configFile} ${cfg.dataDir}/config
|
||||
chown -R '${cfg.user}:${cfg.group}' '${cfg.dataDir}'
|
||||
# The RPC socket has to be removed otherwise we might have stale sockets
|
||||
rm -f ${cfg.networkDir}/lightning-rpc
|
||||
chmod 640 ${cfg.dataDir}/config
|
||||
install -m 640 ${configFile} '${cfg.dataDir}/config'
|
||||
{
|
||||
echo "bitcoin-rpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-public)"
|
||||
${optionalString (cfg.getPublicAddressCmd != "") ''
|
||||
echo "announce-addr=$(${cfg.getPublicAddressCmd})"
|
||||
''}
|
||||
} >> '${cfg.dataDir}/config'
|
||||
|
||||
'';
|
||||
serviceConfig = nbLib.defaultHardening // {
|
||||
ExecStart = "${nbPkgs.clightning}/bin/lightningd --lightning-dir=${cfg.dataDir}";
|
||||
User = "${cfg.user}";
|
||||
User = cfg.user;
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
ReadWritePaths = "${cfg.dataDir}";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // (if cfg.enforceTor
|
||||
then nbLib.allowTor
|
||||
else nbLib.allowAnyIP
|
||||
@ -154,5 +141,12 @@ in {
|
||||
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 = {
|
||||
description = "Electrs Electrum Server";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "bitcoind.service" ];
|
||||
after = [ "bitcoind.service" ];
|
||||
@ -110,7 +109,6 @@ in {
|
||||
};
|
||||
|
||||
users.users.${cfg.user} = {
|
||||
description = "electrs User";
|
||||
group = cfg.group;
|
||||
extraGroups = [ "bitcoinrpc" ] ++ optionals cfg.high-memory [ "bitcoin" ];
|
||||
};
|
||||
|
@ -47,11 +47,12 @@ in {
|
||||
# Provides lsusb for debugging
|
||||
pkgs.usbutils
|
||||
];
|
||||
users.groups."${cfg.group}" = {};
|
||||
|
||||
users.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
|
||||
# Don't use rules from nixpkgs because we want to use our own group.
|
||||
services.udev.packages = lib.singleton (pkgs.writeTextFile {
|
||||
|
@ -46,16 +46,6 @@ in {
|
||||
default = "/var/lib/joinmarket-ob-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
|
||||
enforceTor = mkOption {
|
||||
readOnly = true;
|
||||
@ -64,6 +54,7 @@ in {
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Joinmarket is Tor-only
|
||||
services.tor = {
|
||||
enable = true;
|
||||
client.enable = true;
|
||||
@ -73,27 +64,23 @@ in {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "tor.service" ];
|
||||
after = [ "tor.service" ];
|
||||
# The service writes to HOME/.config/matplotlib
|
||||
environment.HOME = cfg.dataDir;
|
||||
preStart = ''
|
||||
ln -snf ${configFile} ${cfg.dataDir}/joinmarket.cfg
|
||||
'';
|
||||
serviceConfig = nbLib.defaultHardening // rec {
|
||||
DynamicUser = true;
|
||||
StateDirectory = "joinmarket-ob-watcher";
|
||||
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 = ''
|
||||
${nbPkgs.joinmarket}/bin/ob-watcher --datadir=${cfg.dataDir} \
|
||||
--host=${cfg.address} --port=${toString cfg.port}
|
||||
'';
|
||||
User = cfg.user;
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
} // 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 [{
|
||||
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 = [
|
||||
(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 = [
|
||||
"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 = {
|
||||
description = "JoinMarket Daemon";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "bitcoind.service" ];
|
||||
after = [ "bitcoind.service" ];
|
||||
path = [ pkgs.sudo ];
|
||||
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
|
||||
sed -i \
|
||||
"s|@@RPC_PASSWORD@@|rpc_password = $(cat ${secretsDir}/bitcoin-rpcpassword-privileged)|" \
|
||||
'${cfg.dataDir}/joinmarket.cfg'
|
||||
'';
|
||||
# Generating wallets (jmclient/wallet.py) is only supported for mainnet or testnet
|
||||
ExecStartPost = mkIf (bitcoind.network == "mainnet") (nbLib.privileged ''
|
||||
ExecStartPost = mkIf (bitcoind.network == "mainnet")
|
||||
(nbLib.privileged "joinmarket-create-wallet" ''
|
||||
walletname=wallet.jmdat
|
||||
wallet=${cfg.dataDir}/wallets/$walletname
|
||||
if [[ ! -f $wallet ]]; then
|
||||
echo "Create wallet"
|
||||
pw=$(cat "${secretsDir}"/jm-wallet-password)
|
||||
mnemonic=${secretsDir}/jm-wallet-seed
|
||||
if [[ ! -f ${cfg.dataDir}/wallets/$walletname ]]; then
|
||||
echo Create joinmarket wallet
|
||||
# Use bash variables so commands don't proceed on previous failures
|
||||
# (like with pipes)
|
||||
cd ${cfg.dataDir} && \
|
||||
out=$(sudo -u ${cfg.user} \
|
||||
${nbPkgs.joinmarket}/bin/jm-genwallet \
|
||||
--datadir=${cfg.dataDir} $walletname $pw)
|
||||
recoveryseed=$(echo "$out" | grep 'recovery_seed')
|
||||
echo "$recoveryseed" | cut -d ':' -f2 > $mnemonic
|
||||
cd ${cfg.dataDir}
|
||||
if ! sudo -u ${cfg.user} ${nbPkgs.joinmarket}/bin/jm-genwallet --datadir=${cfg.dataDir} $walletname $pw \
|
||||
| grep 'recovery_seed' \
|
||||
| cut -d ':' -f2 \
|
||||
| (umask u=r,go=; cat > "${secretsDir}/jm-wallet-seed"); then
|
||||
echo "wallet creation failed"
|
||||
rm -f "$wallet" "${secretsDir}/jm-wallet-seed"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
'');
|
||||
ExecStart = "${nbPkgs.joinmarket}/bin/joinmarketd";
|
||||
WorkingDirectory = "${cfg.dataDir}"; # The service creates 'commitmentlist' in the working dir
|
||||
User = "${cfg.user}";
|
||||
WorkingDirectory = cfg.dataDir; # The service creates 'commitmentlist' in the working dir
|
||||
User = cfg.user;
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
ReadWritePaths = "${cfg.dataDir}";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // 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;
|
||||
}
|
||||
|
||||
@ -227,7 +231,6 @@ in {
|
||||
chmod +x $out
|
||||
'';
|
||||
in {
|
||||
description = "CoinJoin maker bot to gain privacy and passively generate income";
|
||||
wantedBy = [ "joinmarket.service" ];
|
||||
requires = [ "joinmarket.service" ];
|
||||
after = [ "joinmarket.service" ];
|
||||
@ -242,10 +245,14 @@ in {
|
||||
serviceConfig = nbLib.defaultHardening // rec {
|
||||
RuntimeDirectory = "joinmarket-yieldgenerator"; # Only used to create start script
|
||||
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";
|
||||
User = "${cfg.user}";
|
||||
ReadWritePaths = "${cfg.dataDir}";
|
||||
# Show "joinmarket-yieldgenerator" instead of "bash" in the journal.
|
||||
# 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;
|
||||
};
|
||||
})
|
||||
|
@ -101,7 +101,7 @@ in {
|
||||
User = "lnd";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
ReadWritePaths = "${cfg.dataDir}";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // (if cfg.enforceTor
|
||||
then nbLib.allowTor
|
||||
else nbLib.allowAnyIP);
|
||||
|
@ -87,9 +87,8 @@ in {
|
||||
par=16
|
||||
rpcthreads=16
|
||||
logips=1
|
||||
|
||||
'';
|
||||
description = "Additional configurations to be appended to <filename>elements.conf</filename>.";
|
||||
description = "Extra lines appended to <filename>elements.conf</filename>.";
|
||||
};
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
@ -123,7 +122,7 @@ in {
|
||||
alice.passwordHMAC = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
|
||||
bob.passwordHMAC = "b2dd077cb54591a2f3139e69a897ac$4e71f08d48b4347cf8eff3815c0e25ae2e9a4340474079f55705f40574f4ec99";
|
||||
};
|
||||
type = with types; loaOf (submodule rpcUserOpts);
|
||||
type = with types; attrsOf (submodule rpcUserOpts);
|
||||
description = ''
|
||||
RPC user information for JSON-RPC connections.
|
||||
'';
|
||||
@ -221,25 +220,25 @@ in {
|
||||
];
|
||||
|
||||
systemd.services.liquidd = {
|
||||
description = "Elements daemon providing access to the Liquid sidechain";
|
||||
requires = [ "bitcoind.service" ];
|
||||
after = [ "bitcoind.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
preStart = ''
|
||||
cp '${configFile}' '${cfg.dataDir}/elements.conf'
|
||||
chmod 640 '${cfg.dataDir}/elements.conf'
|
||||
chown -R '${cfg.user}:${cfg.group}' '${cfg.dataDir}'
|
||||
echo "rpcpassword=$(cat ${secretsDir}/liquid-rpcpassword)" >> '${cfg.dataDir}/elements.conf'
|
||||
echo "mainchainrpcpassword=$(cat ${secretsDir}/bitcoin-rpcpassword-public)" >> '${cfg.dataDir}/elements.conf'
|
||||
install -m 640 ${configFile} '${cfg.dataDir}/elements.conf'
|
||||
{
|
||||
echo "rpcpassword=$(cat ${secretsDir}/liquid-rpcpassword)"
|
||||
echo "mainchainrpcpassword=$(cat ${secretsDir}/bitcoin-rpcpassword-public)"
|
||||
} >> '${cfg.dataDir}/elements.conf'
|
||||
'';
|
||||
serviceConfig = nbLib.defaultHardening // {
|
||||
Type = "simple";
|
||||
User = "${cfg.user}";
|
||||
Group = "${cfg.group}";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart = "${nbPkgs.elementsd}/bin/elementsd ${cmdlineOptions}";
|
||||
PIDFile = "${pidFile}";
|
||||
PIDFile = pidFile;
|
||||
Restart = "on-failure";
|
||||
ReadWritePaths = "${cfg.dataDir}";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
} // (if cfg.enforceTor
|
||||
then nbLib.allowTor
|
||||
else nbLib.allowAnyIP
|
||||
@ -249,7 +248,6 @@ in {
|
||||
users.users.${cfg.user} = {
|
||||
group = cfg.group;
|
||||
extraGroups = [ "bitcoinrpc" ];
|
||||
description = "Liquid sidechain user";
|
||||
};
|
||||
users.groups.${cfg.group} = {};
|
||||
nix-bitcoin.operator.groups = [ cfg.group ];
|
||||
|
@ -37,13 +37,7 @@ let
|
||||
in {
|
||||
|
||||
options.services.lnd = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If enabled, the LND service will be installed.
|
||||
'';
|
||||
};
|
||||
enable = mkEnableOption "Lightning Network Daemon";
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/lnd";
|
||||
@ -89,7 +83,7 @@ in {
|
||||
tor-socks = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
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 {
|
||||
default = {};
|
||||
@ -118,7 +112,7 @@ in {
|
||||
example = ''
|
||||
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 {
|
||||
type = types.package;
|
||||
@ -156,9 +150,13 @@ in {
|
||||
|
||||
services.bitcoind = {
|
||||
enable = true;
|
||||
|
||||
# Increase rpc thread count due to reports that lightning implementations fail
|
||||
# under high bitcoind rpc load
|
||||
rpc.threads = 16;
|
||||
|
||||
zmqpubrawblock = "tcp://${bitcoindRpcAddress}:28332";
|
||||
zmqpubrawtx = "tcp://${bitcoindRpcAddress}:28333";
|
||||
};
|
||||
|
||||
environment.systemPackages = [ cfg.package (hiPrio cfg.cli) ];
|
||||
@ -167,13 +165,7 @@ in {
|
||||
"d '${cfg.dataDir}' 0770 lnd lnd - -"
|
||||
];
|
||||
|
||||
services.bitcoind = {
|
||||
zmqpubrawblock = "tcp://${bitcoindRpcAddress}:28332";
|
||||
zmqpubrawtx = "tcp://${bitcoindRpcAddress}:28333";
|
||||
};
|
||||
|
||||
systemd.services.lnd = {
|
||||
description = "Run LND";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "bitcoind.service" ];
|
||||
after = [ "bitcoind.service" ];
|
||||
@ -193,12 +185,12 @@ in {
|
||||
User = "lnd";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
ReadWritePaths = "${cfg.dataDir}";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
ExecStartPost = let
|
||||
restUrl = "https://${cfg.restAddress}:${toString cfg.restPort}/v1";
|
||||
in [
|
||||
# Run fully privileged for secrets dir write access
|
||||
"+${nbLib.script ''
|
||||
(nbLib.privileged "lnd-create-mnemonic" ''
|
||||
attempts=250
|
||||
while ! { exec 3>/dev/tcp/${cfg.restAddress}/${toString cfg.restPort} && exec 3>&-; } &>/dev/null; do
|
||||
((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"
|
||||
fi
|
||||
chown lnd: "$mnemonic"
|
||||
''}"
|
||||
"${nbLib.script ''
|
||||
'')
|
||||
(nbLib.script "lnd-create-wallet" ''
|
||||
if [[ ! -f ${networkDir}/wallet.db ]]; then
|
||||
echo Create lnd wallet
|
||||
|
||||
@ -246,9 +238,9 @@ in {
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
''}"
|
||||
'')
|
||||
# Run fully privileged for chown
|
||||
"+${nbLib.script ''
|
||||
(nbLib.privileged "lnd-create-macaroons" ''
|
||||
umask ug=r,o=
|
||||
${lib.concatMapStrings (macaroon: ''
|
||||
echo "Create custom macaroon ${macaroon}"
|
||||
@ -262,7 +254,7 @@ in {
|
||||
${pkgs.jq}/bin/jq -c '.macaroon' | ${pkgs.xxd}/bin/xxd -p -r > "$macaroonPath"
|
||||
chown ${cfg.macaroons.${macaroon}.user}: "$macaroonPath"
|
||||
'') (attrNames cfg.macaroons)}
|
||||
''}"
|
||||
'')
|
||||
];
|
||||
} // (if cfg.enforceTor
|
||||
then nbLib.allowTor
|
||||
@ -271,7 +263,6 @@ in {
|
||||
};
|
||||
|
||||
users.users.lnd = {
|
||||
description = "LND User";
|
||||
group = "lnd";
|
||||
extraGroups = [ "bitcoinrpc" ];
|
||||
home = cfg.dataDir; # lnd creates .lnd dir in HOME
|
||||
|
@ -105,7 +105,7 @@ in {
|
||||
source = config.nix-bitcoin.pkgs.netns-exec;
|
||||
capabilities = "cap_sys_admin=ep";
|
||||
owner = cfg.allowedUser;
|
||||
permissions = "u+rx,g+rx,o-rwx";
|
||||
permissions = "550";
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
@ -119,7 +119,7 @@ in {
|
||||
after = [ "network-pre.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = "yes";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
${ip} link add name nb-br type bridge
|
||||
@ -182,7 +182,7 @@ in {
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = "yes";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -41,13 +41,7 @@ let
|
||||
'';
|
||||
in {
|
||||
options.services.recurring-donations = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If enabled, the recurring-donations service will be installed.
|
||||
'';
|
||||
};
|
||||
enable = mkEnableOption "recurring-donations";
|
||||
tallycoin = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
@ -81,15 +75,7 @@ in {
|
||||
config = mkIf cfg.enable {
|
||||
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 = {
|
||||
description = "Run recurring-donations";
|
||||
requires = [ "clightning.service" ];
|
||||
after = [ "clightning.service" ];
|
||||
path = with pkgs; [ nix-bitcoin.clightning curl sudo jq ];
|
||||
@ -111,5 +97,11 @@ in {
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
users.users.recurring-donations = {
|
||||
group = "recurring-donations";
|
||||
extraGroups = [ "clightning" ];
|
||||
};
|
||||
users.groups.recurring-donations = {};
|
||||
};
|
||||
}
|
||||
|
@ -23,13 +23,7 @@ let
|
||||
'';
|
||||
in {
|
||||
options.services.spark-wallet = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If enabled, the spark-wallet service will be installed.
|
||||
'';
|
||||
};
|
||||
enable = mkEnableOption "spark-wallet";
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
default = "localhost";
|
||||
@ -61,14 +55,12 @@ in {
|
||||
services.clightning.enable = true;
|
||||
|
||||
users.users.spark-wallet = {
|
||||
description = "spark-wallet User";
|
||||
group = "spark-wallet";
|
||||
extraGroups = [ "clightning" ];
|
||||
};
|
||||
users.groups.spark-wallet = {};
|
||||
|
||||
systemd.services.spark-wallet = {
|
||||
description = "Run spark-wallet";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "clightning.service" ];
|
||||
after = [ "clightning.service" ];
|
||||
|
@ -3,20 +3,20 @@
|
||||
, withGui }:
|
||||
|
||||
with stdenv.lib;
|
||||
stdenv.mkDerivation rec{
|
||||
name = "elements" + (toString (optional (!withGui) "d")) + "-" + version;
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "elements${optionalString (!withGui) "d"}";
|
||||
version = "0.18.1.9";
|
||||
|
||||
src = fetchurl {
|
||||
urls = [
|
||||
"https://github.com/ElementsProject/elements/archive/elements-${version}.tar.gz"
|
||||
];
|
||||
url = "https://github.com/ElementsProject/elements/archive/elements-${version}.tar.gz";
|
||||
# Use ./get-sha256.sh to fetch latest (verified) sha256
|
||||
sha256 = "c6f1b040a896a1aaa7340f5cd48e119c84fef88df5d4c17d5ad5c13783f5b6c7";
|
||||
};
|
||||
|
||||
nativeBuildInputs =
|
||||
[ pkgconfig autoreconfHook ]
|
||||
++ optional withGui wrapQtAppsHook;
|
||||
|
||||
buildInputs = [ openssl db48 boost zlib zeromq
|
||||
miniupnpc protobuf libevent]
|
||||
++ optionals stdenv.isLinux [ utillinux ]
|
||||
@ -27,8 +27,8 @@ stdenv.mkDerivation rec{
|
||||
] ++ optionals (!doCheck) [
|
||||
"--disable-tests"
|
||||
"--disable-gui-tests"
|
||||
]
|
||||
++ optionals withGui [ "--with-gui=qt5"
|
||||
] ++ optionals withGui [
|
||||
"--with-gui=qt5"
|
||||
"--with-qt-bindir=${qtbase.dev}/bin:${qttools.dev}/bin"
|
||||
];
|
||||
|
||||
|
@ -28,8 +28,9 @@ let self = {
|
||||
CapabilityBoundingSet = "";
|
||||
# @system-service whitelist and docker seccomp blacklist (except for "clone"
|
||||
# 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" ];
|
||||
SystemCallArchitectures= "native";
|
||||
SystemCallArchitectures = "native";
|
||||
};
|
||||
|
||||
# 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
|
||||
${src}
|
||||
'';
|
||||
|
||||
# Used for ExecStart*
|
||||
privileged = src: "+${self.script src}";
|
||||
privileged = name: src: "+${self.script name src}";
|
||||
|
||||
cliExec = mkOption {
|
||||
# Used by netns-isolation to execute the cli in the service's private netns
|
||||
|
@ -6,7 +6,7 @@ buildPythonPackage rec {
|
||||
src = fetchFromGitHub {
|
||||
owner = "freelan-developers";
|
||||
repo = "chromalog";
|
||||
rev = "${version}";
|
||||
rev = version;
|
||||
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.
|
||||
# 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`.
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
scriptDir=$(cd "${BASH_SOURCE[0]%/*}" && pwd)
|
||||
|
||||
args=("$@")
|
||||
scenario=
|
||||
outLinkPrefix=
|
||||
ciBuild=
|
||||
@ -77,6 +85,13 @@ while :; do
|
||||
shift
|
||||
ciBuild=1
|
||||
;;
|
||||
--copy-src|-c)
|
||||
shift
|
||||
if [[ ! $_nixBitcoinInCopySrc ]]; then
|
||||
. "$scriptDir/lib/copy-src.sh"
|
||||
exit
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
break
|
||||
esac
|
||||
@ -172,7 +187,7 @@ doBuild() {
|
||||
|
||||
# Run the test by building the test derivation
|
||||
buildTest() {
|
||||
vmTestNixExpr | doBuild $scenario $outLinkArg "$@" -
|
||||
vmTestNixExpr | doBuild $scenario "$@" -
|
||||
}
|
||||
|
||||
vmTestNixExpr() {
|
||||
|
Loading…
Reference in New Issue
Block a user