Merge fort-nix/nix-bitcoin#586: Misc. improvements

addfa8ec6b test: support `run`, `debug` commands in basic NixOS tests (Erik Arvstedt)
ae733d887e tests/clightning-replication: reuse `pkgs` instance (Erik Arvstedt)
6cbd0d93ae tests: rename `clightningReplication` -> `clightning-replication` (Erik Arvstedt)
85310b533a secrets: use type `lines` for `generateSecretsCmds` (Erik Arvstedt)
bc2f66d4f1 bitcoind, liquid: increase start/stop timeouts (Erik Arvstedt)
519ae31202 netns-isolation: improve formatting (Erik Arvstedt)
a1023696e6 netns-isolation: reserve netns id for mempool (Erik Arvstedt)
34fe8675bd add option `nix-bitcoin.pkgOverlays` (Erik Arvstedt)
a3bdecb10b helper: add start-bash-session.sh (Erik Arvstedt)
690a8f6256 nodeinfo: extract fn `mkInfoLong` (Erik Arvstedt)
2af642f56a improve comments (Erik Arvstedt)
5634f08873 rtl: make `extraConfig` recursively mergeable (Erik Arvstedt)
b76728a1ec treewide: use bool literals for systemd (Erik Arvstedt)

Pull request description:

ACKs for top commit:
  jonasnick:
    ACK addfa8ec6b

Tree-SHA512: 46f779f8477b566ffc6d0dfb024f2098757f509b2b3e0cbb509cf3308de7029e913f6e6c3d6d3d226cc72f8a5031fd5586b2efdf7c2d9d15f4bdd7ed08b27425
This commit is contained in:
Jonas Nick 2023-02-03 13:11:34 +00:00
commit 475af2d6cb
No known key found for this signature in database
GPG Key ID: 4861DBF262123605
20 changed files with 91 additions and 54 deletions

View File

@ -55,7 +55,7 @@ The [nix-bitcoin test suite](../test/README.md) is also useful for exploring fea
### Real-world example ### Real-world example
Check the [server repo](https://github.com/fort-nix/nixbitcoin.org) for https://nixbitcoin.org Check the [server repo](https://github.com/fort-nix/nixbitcoin.org) for https://nixbitcoin.org
to see the configuration of a nix-bitcoin node that's used in production. to see the configuration of a Flakes-based nix-bitcoin node that's used in production.
The commands in `shell.nix` allow you to locally run the node in a VM or container. The commands in `shell.nix` allow you to locally run the node in a VM or container.

View File

@ -0,0 +1,12 @@
# Start an interactive bash session in the current bash environment.
# This is helpful for debugging bash scripts like pkg update scripts,
# by adding `source <path-to>/start-bash-session.sh` at the location to
# be inspected.
# BASH_ENVIRONMENT contains definitions of read-only variables like 'BASHOPTS' that
# cause warnings on evaluation. Suppress these warnings while sourcing.
#
# shellcheck disable=SC2016
BASH_ENVIRONMENT=<(declare -p; declare -pf) \
bash --rcfile <(echo 'source $BASH_ENVIRONMENT 2>/dev/null')

View File

@ -421,8 +421,8 @@ in {
NotifyAccess = "all"; NotifyAccess = "all";
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
TimeoutStartSec = "10min"; TimeoutStartSec = "30min";
TimeoutStopSec = "10min"; TimeoutStopSec = "30min";
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";

View File

@ -193,7 +193,7 @@ in {
Restart = "on-failure"; Restart = "on-failure";
RestartSec = "10s"; RestartSec = "10s";
ReadWritePaths = [ cfg.nbxplorer.dataDir ]; ReadWritePaths = [ cfg.nbxplorer.dataDir ];
MemoryDenyWriteExecute = "false"; MemoryDenyWriteExecute = false;
} // nbLib.allowedIPAddresses cfg.nbxplorer.tor.enforce; } // nbLib.allowedIPAddresses cfg.nbxplorer.tor.enforce;
}; };
@ -239,7 +239,7 @@ in {
Restart = "on-failure"; Restart = "on-failure";
RestartSec = "10s"; RestartSec = "10s";
ReadWritePaths = [ cfg.btcpayserver.dataDir ]; ReadWritePaths = [ cfg.btcpayserver.dataDir ];
MemoryDenyWriteExecute = "false"; MemoryDenyWriteExecute = false;
} // nbLib.allowedIPAddresses cfg.btcpayserver.tor.enforce; } // nbLib.allowedIPAddresses cfg.btcpayserver.tor.enforce;
}; in self; }; in self;

View File

@ -17,8 +17,8 @@ let cfg = config.services.clightning.plugins.clboss; in
default = 30000; default = 30000;
description = mdDoc '' description = mdDoc ''
Target amount (in satoshi) that CLBOSS will leave on-chain. Target amount (in satoshi) that CLBOSS will leave on-chain.
clboss will only open new channels if this amount is smaller than clboss will only open new channels if the funds in your clightning wallet are
the funds in your clightning wallet. larger than this amount.
''; '';
}; };
min-channel = mkOption { min-channel = mkOption {

View File

@ -270,8 +270,8 @@ in {
NotifyAccess = "all"; NotifyAccess = "all";
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
TimeoutStartSec = "10min"; TimeoutStartSec = "2h";
TimeoutStopSec = "10min"; TimeoutStopSec = "2h";
ExecStart = "${nbPkgs.elementsd}/bin/elementsd -datadir='${cfg.dataDir}'"; ExecStart = "${nbPkgs.elementsd}/bin/elementsd -datadir='${cfg.dataDir}'";
Restart = "on-failure"; Restart = "on-failure";
ReadWritePaths = [ cfg.dataDir ]; ReadWritePaths = [ cfg.dataDir ];

View File

@ -215,9 +215,11 @@ in {
}; };
}; };
in foldl (services: n: in
foldl (services: n:
services // (makeNetnsServices n netns.${n}) services // (makeNetnsServices n netns.${n})
) {} (builtins.attrNames netns)); ) {} (builtins.attrNames netns)
);
} }
# Service-specific config # Service-specific config
@ -297,6 +299,7 @@ in {
id = 31; id = 31;
connections = [ "bitcoind" ]; connections = [ "bitcoind" ];
}; };
# id = 32 reserved for the upcoming mempool module
}; };
services.bitcoind = { services.bitcoind = {

View File

@ -1,4 +1,4 @@
{ config, pkgs, lib, ... }: { config, options, pkgs, lib, ... }:
with lib; with lib;
{ {
@ -8,6 +8,18 @@ with lib;
type = types.attrs; type = types.attrs;
default = (import ../pkgs { inherit pkgs; }).modulesPkgs; default = (import ../pkgs { inherit pkgs; }).modulesPkgs;
defaultText = "nix-bitcoin/pkgs.modulesPkgs"; defaultText = "nix-bitcoin/pkgs.modulesPkgs";
apply = base:
let
final = foldl (prev: overlay:
prev // (overlay prev final)
) base options.nix-bitcoin.pkgOverlays.definitions;
in
final;
};
pkgOverlays = mkOption {
internal = true;
type = with types; functionTo attrs;
}; };
lib = mkOption { lib = mkOption {

View File

@ -73,9 +73,10 @@ let
return return
info["onion_address"] = f"{onion_address}:{port}" info["onion_address"] = f"{onion_address}:{port}"
def add_service(service, make_info): def add_service(service, make_info, systemd_service = None):
if not is_active(service): systemd_service = systemd_service or service
infos[service] = "service is not running" if not is_active(systemd_service):
infos[service] = f"'{systemd_service}.service' is not running"
else: else:
info = OrderedDict() info = OrderedDict()
exec(make_info, globals(), locals()) exec(make_info, globals(), locals())
@ -96,14 +97,19 @@ let
) (builtins.attrNames cfg.services); ) (builtins.attrNames cfg.services);
nodeinfoLib = rec { nodeinfoLib = rec {
mkInfo = extraCode: name: cfg: '' mkInfo = extraCode: name: cfg:
mkInfoLong {
inherit extraCode name cfg;
};
mkInfoLong = { extraCode ? "", name, cfg, systemdServiceName ? name }: ''
add_service("${name}", """ add_service("${name}", """
info["local_address"] = "${nbLib.addressWithPort cfg.address cfg.port}" info["local_address"] = "${nbLib.addressWithPort cfg.address cfg.port}"
'' + mkIfOnionPort name (onionPort: '' '' + mkIfOnionPort name (onionPort: ''
set_onion_address(info, "${name}", ${onionPort}) set_onion_address(info, "${name}", ${onionPort})
'') + extraCode + '' '') + extraCode + ''
""") """, "${systemdServiceName}")
''; '';
mkIfOnionPort = name: fn: mkIfOnionPort = name: fn:

View File

@ -55,8 +55,8 @@ in {
RemainAfterExit = true; RemainAfterExit = true;
StateDirectory = "onion-addresses"; StateDirectory = "onion-addresses";
StateDirectoryMode = "771"; StateDirectoryMode = "771";
PrivateNetwork = "true"; # This service needs no network access PrivateNetwork = true; # This service needs no network access
PrivateUsers = "false"; PrivateUsers = false;
CapabilityBoundingSet = "CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_IPC_OWNER"; CapabilityBoundingSet = "CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_IPC_OWNER";
}; };
script = '' script = ''

View File

@ -5,7 +5,9 @@ let
secretsDir = config.nix-bitcoin.secretsDir; secretsDir = config.nix-bitcoin.secretsDir;
in { in {
services.bitcoind = { services.bitcoind = {
# Make the local bitcoin-cli work with the remote node # Make the local bitcoin-cli work with the remote node.
# Without this, bitcoin-cli would try to use the .cookie file in the local
# bitcoind data dir for authorization, which doesn't exist.
extraConfig = '' extraConfig = ''
rpcuser=${cfg.rpc.users.privileged.name} rpcuser=${cfg.rpc.users.privileged.name}
''; '';

View File

@ -27,7 +27,7 @@ let
description = mdDoc "Enable the clightning node interface."; description = mdDoc "Enable the clightning node interface.";
}; };
extraConfig = mkOption { extraConfig = mkOption {
type = types.attrs; type = with types; attrsOf anything;
default = {}; default = {};
example = { example = {
Settings.userPersona = "MERCHANT"; Settings.userPersona = "MERCHANT";
@ -52,7 +52,7 @@ let
description = mdDoc "Enable swaps with lightning-loop."; description = mdDoc "Enable swaps with lightning-loop.";
}; };
extraConfig = mkOption { extraConfig = mkOption {
type = types.attrs; type = with types; attrsOf anything;
default = {}; default = {};
example = { example = {
Settings.userPersona = "MERCHANT"; Settings.userPersona = "MERCHANT";

View File

@ -28,7 +28,7 @@ let
}; };
generateSecretsCmds = mkOption { generateSecretsCmds = mkOption {
type = types.attrsOf types.str; type = types.attrsOf types.lines;
default = {}; default = {};
description = mdDoc '' description = mdDoc ''
Bash expressions for generating secrets. Bash expressions for generating secrets.

View File

@ -7,28 +7,28 @@ with lib;
let self = { let self = {
# These settings roughly follow systemd's "strict" security profile # These settings roughly follow systemd's "strict" security profile
defaultHardening = { defaultHardening = {
PrivateTmp = "true"; PrivateTmp = true;
ProtectSystem = "strict"; ProtectSystem = "strict";
ProtectHome = "true"; ProtectHome = true;
NoNewPrivileges = "true"; NoNewPrivileges = true;
PrivateDevices = "true"; PrivateDevices = true;
MemoryDenyWriteExecute = "true"; MemoryDenyWriteExecute = true;
ProtectKernelTunables = "true"; ProtectKernelTunables = true;
ProtectKernelModules = "true"; ProtectKernelModules = true;
ProtectKernelLogs = "true"; ProtectKernelLogs = true;
ProtectClock = "true"; ProtectClock = true;
ProtectProc = "invisible"; ProtectProc = "invisible";
ProcSubset = "pid"; ProcSubset = "pid";
ProtectControlGroups = "true"; ProtectControlGroups = true;
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
RestrictNamespaces = "true"; RestrictNamespaces = true;
LockPersonality = "true"; LockPersonality = true;
IPAddressDeny = "any"; IPAddressDeny = "any";
PrivateUsers = "true"; PrivateUsers = true;
RestrictSUIDSGID = "true"; RestrictSUIDSGID = true;
RemoveIPC = "true"; RemoveIPC = true;
RestrictRealtime = "true"; RestrictRealtime = true;
ProtectHostname = "true"; ProtectHostname = true;
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)
@ -42,7 +42,7 @@ let self = {
}; };
# nodejs applications require memory write execute for JIT compilation # nodejs applications require memory write execute for JIT compilation
nodejs = { MemoryDenyWriteExecute = "false"; }; nodejs = { MemoryDenyWriteExecute = false; };
# Allow takes precedence over Deny. # Allow takes precedence over Deny.
allowLocalIPAddresses = { allowLocalIPAddresses = {

View File

@ -39,7 +39,6 @@ rec {
## Specific versions of packages that already exist in nixpkgs ## Specific versions of packages that already exist in nixpkgs
# cryptography 3.3.2, required by joinmarketdaemon # cryptography 3.3.2, required by joinmarketdaemon
# Used in the private python package set for joinmarket (../joinmarket/default.nix)
cryptography = callPackage ./specific-versions/cryptography { cryptography = callPackage ./specific-versions/cryptography {
openssl = super.pkgs.openssl_1_1; openssl = super.pkgs.openssl_1_1;
cryptography_vectors = callPackage ./specific-versions/cryptography/vectors.nix {}; cryptography_vectors = callPackage ./specific-versions/cryptography/vectors.nix {};

View File

@ -1,4 +1,4 @@
# You can run this test via `run-tests.sh -s clightningReplication` # You can run this test via `run-tests.sh -s clightning-replication`
makeTestVM: pkgs: makeTestVM: pkgs:
with pkgs.lib; with pkgs.lib;
@ -14,6 +14,8 @@ let
clientBaseConfig = { clientBaseConfig = {
imports = [ ../modules/modules.nix ]; imports = [ ../modules/modules.nix ];
nixpkgs.pkgs = pkgs;
nix-bitcoin.generateSecrets = true; nix-bitcoin.generateSecrets = true;
services.clightning = { services.clightning = {
@ -54,7 +56,9 @@ makeTestVM {
services.clightning.replication.encrypt = true; services.clightning.replication.encrypt = true;
}; };
server = { ... }: { server = {
nixpkgs.pkgs = pkgs;
environment.etc."ssh-host-key" = { environment.etc."ssh-host-key" = {
source = keys.server; source = keys.server;
mode = "400"; mode = "400";

View File

@ -27,4 +27,9 @@ let
inherit (test) meta passthru; inherit (test) meta passthru;
} // test; } // test;
in in
runTest runTest // {
# A VM runner for interactive use
run = pkgs.writers.writeBashBin "run-vm" ''
. ${./run-vm.sh} ${runTest.driver} "$@"
'';
}

View File

@ -52,11 +52,6 @@ let
]; ];
}; };
# A VM runner for interactive use
run = pkgs.writers.writeBashBin "run-vm" ''
. ${./run-vm.sh} ${test.driver} "$@"
'';
mkContainer = legacyInstallDirs: mkContainer = legacyInstallDirs:
extra-container.lib.buildContainers { extra-container.lib.buildContainers {
inherit system legacyInstallDirs; inherit system legacyInstallDirs;
@ -139,7 +134,6 @@ let
in in
test // { test // {
inherit inherit
run
vm vm
container container
# For NixOS with `system.stateVersion` <22.05 # For NixOS with `system.stateVersion` <22.05

View File

@ -272,7 +272,7 @@ buildable=(
full full
regtest regtest
hardened hardened
clightningReplication clightning-replication
lndPruned lndPruned
) )
buildable() { buildTests buildable "$@"; } buildable() { buildTests buildable "$@"; }

View File

@ -404,7 +404,7 @@ in {
) scenarios; ) scenarios;
in in
{ {
clightningReplication = import ./clightning-replication.nix makeTestVM pkgs; clightning-replication = import ./clightning-replication.nix makeTestVM pkgs;
} // mainTests; } // mainTests;
tests = makeTests scenarios; tests = makeTests scenarios;