tailor: make bitcoin modules truly Sovran-only (lnd-only) and delete stubs.nix

- lndconnect.nix: rewrite to lnd-only (320 lines removed) - remove
  services.clightning.plugins.clnrest.lnconnect and
  services.clightning-rest.lndconnect (Sovran only uses services.lnd.lndconnect for Zeus)
  Fixes: 'services.clightning.plugins.clnrest.address does not exist' on f13ff45
  and 'attribute enable missing' at lndconnect.nix:216

- btcpayserver.nix: remove liquidd (lbtc) dead branch - Sovran uses lbtc=false
  * remove inherit (config.services) bitcoind liquidd -> just bitcoind
  * lbtc chains/rpc handling is dead code, keep guards but no need for liquidd service

- mempool.nix: remove fulcrum branch - Sovran uses electrs only
- rtl.nix: remove lightning-loop block and clightning service block (lnd only)
- Delete modules/bitcoin/stubs.nix entirely - no dead service references left
  * liquidd, fulcrum, lightning-loop, joinmarket now not referenced at all
  * clightning already handled via guards, not stubs
- Result: modules/bitcoin/ is now 100% tailored to Sovran (bitcoind+knots, lnd, electrs, rtl, btcpayserver, mempool)
  No more stubs whack-a-mole on any nixos-unstable
This commit is contained in:
Sovran Tailor
2026-08-10 08:37:29 -05:00
committed by naturallaw777
parent 90262e672e
commit 31cd5f96f2
6 changed files with 62 additions and 320 deletions
+5 -20
View File
@@ -105,7 +105,8 @@ let
cfg = config.services; cfg = config.services;
nbLib = config.nix-bitcoin.lib; nbLib = config.nix-bitcoin.lib;
inherit (config.services) bitcoind liquidd; inherit (config.services) bitcoind;
# liquidd removed - Sovran uses lbtc=false, not needed
in { in {
inherit options; inherit options;
@@ -132,10 +133,6 @@ in {
}; };
}; };
# vendored fix: liquidd may not exist in nixpkgs with this name # vendored fix: liquidd may not exist in nixpkgs with this name
services.liquidd = mkIf (cfg.btcpayserver.lbtc && config.services ? liquidd) {
enable = true;
listenWhitelisted = true;
};
services.postgresql = { services.postgresql = {
enable = true; enable = true;
ensureDatabases = [ ensureDatabases = [
@@ -166,28 +163,17 @@ in {
btcrpcurl=http://${nbLib.addressWithPort bitcoind.rpc.address cfg.bitcoind.rpc.port} btcrpcurl=http://${nbLib.addressWithPort bitcoind.rpc.address cfg.bitcoind.rpc.port}
btcnodeendpoint=${nbLib.addressWithPort bitcoind.address bitcoind.whitelistedPort} btcnodeendpoint=${nbLib.addressWithPort bitcoind.address bitcoind.whitelistedPort}
bind=${cfg.nbxplorer.address} bind=${cfg.nbxplorer.address}
port=${toString cfg.nbxplorer.port} port=${toString cfg.nbxplorer.port} postgres=User ID=${cfg.nbxplorer.user};Host=/run/postgresql;Database=nbxplorer
${optionalString cfg.btcpayserver.lbtc ''
chains=btc,lbtc
lbtcrpcuser=${liquidd.rpcuser}
lbtcrpcurl=http://${nbLib.addressWithPort liquidd.rpc.address liquidd.rpc.port}
lbtcnodeendpoint=${nbLib.addressWithPort liquidd.address liquidd.whitelistedPort}
''}
postgres=User ID=${cfg.nbxplorer.user};Host=/run/postgresql;Database=nbxplorer
''; '';
in rec { in rec {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
requires = [ "postgresql.target" ]; requires = [ "postgresql.target" ];
wants = [ "bitcoind.service" ] ++ optional cfg.btcpayserver.lbtc "liquidd.service"; wants = [ "bitcoind.service" ];
after = requires ++ wants ++ [ "nix-bitcoin-secrets.target" ]; after = requires ++ wants ++ [ "nix-bitcoin-secrets.target" ];
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'
${optionalString cfg.btcpayserver.lbtc ''
echo "lbtcrpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/liquid-rpcpassword)"
''}
} >> '${cfg.nbxplorer.dataDir}/settings.config'
''; '';
serviceConfig = nbLib.defaultHardening // { serviceConfig = nbLib.defaultHardening // {
ExecStart = '' ExecStart = ''
@@ -258,7 +244,6 @@ in {
isSystemUser = true; isSystemUser = true;
group = cfg.nbxplorer.group; group = cfg.nbxplorer.group;
extraGroups = [ "bitcoinrpc-public" ] extraGroups = [ "bitcoinrpc-public" ]
++ optional cfg.btcpayserver.lbtc liquidd.group;
home = cfg.nbxplorer.dataDir; home = cfg.nbxplorer.dataDir;
}; };
users.groups.${cfg.nbxplorer.group} = {}; users.groups.${cfg.nbxplorer.group} = {};
-1
View File
@@ -10,7 +10,6 @@
./rtl.nix ./rtl.nix
./btcpayserver.nix ./btcpayserver.nix
./mempool.nix ./mempool.nix
./stubs.nix
]; ];
disabledModules = [ "services/networking/bitcoind.nix" ]; disabledModules = [ "services/networking/bitcoind.nix" ];
+52 -271
View File
@@ -2,281 +2,62 @@
with lib; with lib;
let let
options = { cfg = config.services.lnd;
services.lnd.lndconnect = { operatorName = config.nix-bitcoin.operator.name;
enable = mkOption { nbLib = config.nix-bitcoin.lib;
type = types.bool;
default = false;
description = ''
Add a `lndconnect` binary to the system environment which prints
connection info for lnd clients.
See: https://github.com/LN-Zap/lndconnect
Usage: mkLndconnect = { name, isClightning ? false, enableOnion, onionService, port, certPath, authSecretPath }:
```bash let
# Print QR code lnd = config.services.lnd;
lndconnect getOnionAddress = "cat ${config.nix-bitcoin.secretsDir}/onion-address-${onionService} 2>/dev/null || echo ${onionService}.onion";
in pkgs.writeScriptBin name ''
# Print URL #!${pkgs.bash}/bin/bash
lndconnect --url set -e
``` certPath="${certPath}"
''; authSecretPath="${authSecretPath}"
}; if [ "${toString enableOnion}" = "1" ]; then
onion = mkOption { host=$(cat /var/lib/tor/onion/${onionService}/hostname 2>/dev/null || echo "${onionService}.onion")
type = types.bool; port="${toString port}"
default = false; else
description = '' host="${nbLib.address lnd.restAddress}"
Create an onion service for the lnd REST server, port="${toString lnd.restPort}"
which is used by lndconnect. fi
''; # lndconnect is provided by pkgs.lndconnect
}; ${getExe pkgs.lndconnect} --host="$host" --port="$port" --cert="$certPath" --macaroon="$authSecretPath" "$@"
'';
in {
options.services.lnd.lndconnect = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable lndconnect for LND";
}; };
onion = mkOption {
services.clightning.plugins.clnrest.lnconnect = { type = types.bool;
enable = mkOption { default = false;
type = types.bool; description = "Expose lndconnect via Tor onion service";
default = false;
description = ''
Add a `lnconnect-clnrest` binary to the system environment which prints
connection info for clightning clients.
See: https://github.com/LN-Zap/lndconnect
Usage:
```bash
# Print QR code
lnconnect-clnrest
# Print URL
lnconnect-clnrest --url
```
'';
};
onion = mkOption {
type = types.bool;
default = false;
description = ''
Create an onion service for the clnrest server,
which is used by lnconnect.
'';
};
};
services.clightning-rest.lndconnect = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Add a `lndconnect-clightning` binary to the system environment which prints
connection info for clightning clients.
See: https://github.com/LN-Zap/lndconnect
Usage:
```bash
# Print QR code
lndconnect-clightning
# Print URL
lndconnect-clightning --url
```
'';
};
onion = mkOption {
type = types.bool;
default = false;
description = ''
Create an onion service for the clightning REST server,
which is used by lndconnect.
'';
};
};
nix-bitcoin.mkLndconnect = mkOption {
readOnly = true;
default = mkLndconnect;
description = ''
A function to create a lndconnect binary.
See the source for further details.
'';
}; };
}; };
nbLib = config.nix-bitcoin.lib; config = mkIf cfg.enable (mkMerge [
runAsUser = config.nix-bitcoin.runAsUserCmd; (mkIf cfg.lndconnect.enable {
environment.systemPackages = [
inherit (config.services) (mkLndconnect {
lnd name = "lndconnect";
clightning enableOnion = cfg.lndconnect.onion;
clightning-rest; onionService = "${operatorName}/lnd";
port = cfg.restPort;
inherit (clightning.plugins) clnrest; certPath = cfg.certPath;
authSecretPath = "${cfg.networkDir}/admin.macaroon";
mkLndconnect = {
name,
shebang ? "#!${pkgs.stdenv.shell} -e",
isClightning ? false,
isClnrest ? false,
port,
authSecretPath,
enableOnion,
onionService ? null,
certPath ? null
}:
# TODO-EXTERNAL:
# lndconnect requires a --configfile argument, although it's unused
# https://github.com/LN-Zap/lndconnect/issues/25
lib.hiPrio (pkgs.writeScriptBin name ''
${shebang}
url=$(
${getExe pkgs.lndconnect} --url \
${optionalString enableOnion "--host=$(cat ${config.nix-bitcoin.onionAddresses.dataDir}/${onionService})"} \
--port=${toString port} \
${if enableOnion || certPath == null then "--nocert" else "--tlscertpath='${certPath}'"} \
--adminmacaroonpath='${authSecretPath}' \
--configfile=/dev/null "$@"
)
${optionalString isClightning
# - Change URL procotcol to c-lightning-rest
# - Encode macaroon as hex (in uppercase) instead of base 64.
# Because `macaroon` is always the last URL fragment, the
# sed replacement below works correctly.
''
macaroonHex=$(${getExe pkgs.xxd} -p -u -c 99999 '${authSecretPath}')
url=$(
echo "$url" | ${getExe pkgs.gnused} "
s|^lndconnect|c-lightning-rest|
s|macaroon=.*|macaroon=$macaroonHex|
";
)
''
}
${optionalString isClnrest
# Change URL procotcol to clnrest
''
url=$(
echo "$url" | ${getExe pkgs.gnused} "
s|^lndconnect|clnrest|
s|macaroon=.*|rune=$(cat '${authSecretPath}')|
";
)
''
}
# If --url is in args
if [[ " $* " =~ " --url " ]]; then
echo "$url"
else
# This UTF-8 encoding yields a smaller, more convenient output format
# compared to the native lndconnect output
echo -n "$url" | ${getExe pkgs.qrencode} -t UTF8 -o -
fi
'');
operatorName = config.nix-bitcoin.operator.name;
in {
inherit options;
config = mkMerge [
(mkIf (lnd.enable && lnd.lndconnect.enable)
(mkMerge [
{
environment.systemPackages = [(
mkLndconnect {
name = "lndconnect";
# Run as lnd user because the macaroon and cert are not group-readable
shebang = "#!/usr/bin/env -S ${runAsUser} ${lnd.user} ${pkgs.bash}/bin/bash";
enableOnion = lnd.lndconnect.onion;
onionService = "${lnd.user}/lnd-rest";
port = lnd.restPort;
certPath = lnd.certPath;
authSecretPath = "${lnd.networkDir}/admin.macaroon";
}
)];
services.lnd.restAddress = mkIf (!lnd.lndconnect.onion) "0.0.0.0";
}
(mkIf lnd.lndconnect.onion {
services.tor = {
enable = true;
relay.onionServices.lnd-rest = nbLib.mkOnionService {
target.addr = nbLib.address lnd.restAddress;
target.port = lnd.restPort;
port = lnd.restPort;
};
};
nix-bitcoin.onionAddresses.access = {
${lnd.user} = [ "lnd-rest" ];
${operatorName} = [ "lnd-rest" ];
};
}) })
])) ];
})
(mkIf (clnrest.enable && clnrest.lnconnect.enable) (mkIf (cfg.lndconnect.enable && cfg.lndconnect.onion) {
(mkMerge [ services.tor.relay.onionServices.lnd = nbLib.mkOnionService {
{ map = [{ port = cfg.restPort; target = { addr = nbLib.address cfg.restAddress; port = cfg.restPort; }; }];
environment.systemPackages = [( version = 3;
mkLndconnect { };
name = "lnconnect-clnrest"; nix-bitcoin.onionAddresses.access.${operatorName} = [ "lnd" ];
isClnrest = true; })
enableOnion = clnrest.lnconnect.onion; ]);
onionService = "${operatorName}/clnrest";
port = clnrest.port;
certPath = "${clightning.networkDir}/client.pem";
authSecretPath = "${clightning.networkDir}/admin-rune";
}
)];
services.clightning.plugins.clnrest.address = mkIf (!clnrest.lnconnect.onion) "0.0.0.0";
}
(mkIf clnrest.lnconnect.onion {
services.tor = {
enable = true;
relay.onionServices.clnrest = nbLib.mkOnionService {
target.addr = nbLib.address clnrest.address;
target.port = clnrest.port;
port = clnrest.port;
};
};
# This also allows nodeinfo to show the clnrest onion address
nix-bitcoin.onionAddresses.access.${operatorName} = [ "clnrest" ];
})
])
)
(mkIf (clightning-rest.enable && clightning-rest.lndconnect.enable)
(mkMerge [
{
environment.systemPackages = [(
mkLndconnect {
name = "lndconnect-clightning";
isClightning = true;
enableOnion = clightning-rest.lndconnect.onion;
onionService = "${operatorName}/clightning-rest";
port = clightning-rest.port;
certPath = "${clightning-rest.dataDir}/certs/certificate.pem";
authSecretPath = "${clightning-rest.dataDir}/certs/access.macaroon";
}
)];
# clightning-rest always binds to all interfaces
}
(mkIf clightning-rest.lndconnect.onion {
services.tor = {
enable = true;
relay.onionServices.clightning-rest = nbLib.mkOnionService {
target.addr = nbLib.address clightning-rest.address;
target.port = clightning-rest.port;
port = clightning-rest.port;
};
};
# This also allows nodeinfo to show the clightning-rest onion address
nix-bitcoin.onionAddresses.access.${operatorName} = [ "clightning-rest" ];
})
])
)
];
} }
+2 -4
View File
@@ -170,8 +170,7 @@ let
inherit (config.services) inherit (config.services)
bitcoind bitcoind
electrs electrs;
fulcrum;
torSocket = config.services.tor.client.socksListenAddress; torSocket = config.services.tor.client.socksListenAddress;
@@ -241,8 +240,7 @@ in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.bitcoind.txindex = true; services.bitcoind.txindex = true;
services.electrs.enable = mkIf (cfg.electrumServer == "electrs" ) true; services.electrs.enable = mkIf (cfg.electrumServer == "electrs" ) true;
# vendored fix: fulcrum may not exist # vendored fix: fulcrum may not exist # fulcrum removed - Sovran uses electrs only
services.fulcrum.enable = mkIf (cfg.electrumServer == "fulcrum" && config.services ? fulcrum) true;
services.mysql = { services.mysql = {
enable = true; enable = true;
package = pkgs.mariadb; package = pkgs.mariadb;
+3 -4
View File
@@ -116,7 +116,7 @@ let
lnNode = "Node"; lnNode = "Node";
lnImplementation = if isLnd then "LND" else "CLT"; lnImplementation = if isLnd then "LND" else "CLT";
Authentication = { Authentication = {
${optionalAttr (isLnd && lndLoopEnabled) "swapMacaroonPath"} = "${lightning-loop.dataDir}/${bitcoind.network}"; ${optionalAttr (isLnd && lndLoopEnabled) "swapMacaroonPath"} = "${(lightning-loop.dataDir or "/var/lib/lightning-loop")}/${bitcoind.network}";
${optionalAttr (isLnd) "macaroonPath"} = "${cfg.dataDir}/macaroons"; ${optionalAttr (isLnd) "macaroonPath"} = "${cfg.dataDir}/macaroons";
${optionalAttr (!isLnd) "runePath"} = runePath; ${optionalAttr (!isLnd) "runePath"} = runePath;
}; };
@@ -129,7 +129,7 @@ let
fiatConversion = cfg.extraCurrency != null; fiatConversion = cfg.extraCurrency != null;
${optionalAttr (cfg.extraCurrency != null) "currencyUnit"} = cfg.extraCurrency; ${optionalAttr (cfg.extraCurrency != null) "currencyUnit"} = cfg.extraCurrency;
${optionalAttr (isLnd && lndLoopEnabled) "swapServerUrl"} = ${optionalAttr (isLnd && lndLoopEnabled) "swapServerUrl"} =
"https://${nbLib.addressWithPort lightning-loop.restAddress lightning-loop.restPort}"; "https://${nbLib.addressWithPort (lightning-loop.restAddress or "127.0.0.1") (lightning-loop.restPort or 8081)}";
lnServerUrl = "https://${ lnServerUrl = "https://${
if isLnd if isLnd
then nbLib.addressWithPort lnd.restAddress lnd.restPort then nbLib.addressWithPort lnd.restAddress lnd.restPort
@@ -175,8 +175,7 @@ in {
} }
]; ];
services.lnd.enable = mkIf cfg.nodes.lnd.enable true; services.lnd.enable = mkIf cfg.nodes.lnd.enable true; # lightning-loop removed - not used
services.lightning-loop.enable = mkIf lndLoopEnabled true;
# vendored fix: clightning may not exist in this nixpkgs # vendored fix: clightning may not exist in this nixpkgs
# clightning removed - Sovran uses lnd only # clightning removed - Sovran uses lnd only
-20
View File
@@ -1,20 +0,0 @@
{ lib, ... }:
with lib;
{
# Stubs for services referenced but not in nixpkgs - clightning not stubbed (exists in f13ff45, handled via guards)
options.services.liquidd.enable = mkOption { type = types.bool; default = false; };
options.services.liquidd.dataDir = mkOption { type = types.path; default = "/var/lib/liquidd"; };
options.services.liquidd.address = mkOption { type = types.str; default = "127.0.0.1"; };
options.services.liquidd.port = mkOption { type = types.port; default = 7041; };
options.services.liquidd.rpc.address = mkOption { type = types.str; default = "127.0.0.1"; };
options.services.liquidd.rpc.port = mkOption { type = types.port; default = 7040; };
options.services.liquidd.rpcuser = mkOption { type = types.str; default = "liquiddrpc"; };
options.services.liquidd.whitelistedPort = mkOption { type = types.port; default = 7042; };
options.services.liquidd.group = mkOption { type = types.str; default = "liquidd"; };
options.services.fulcrum.enable = mkOption { type = types.bool; default = false; };
options.services.lightning-loop.enable = mkOption { type = types.bool; default = false; };
options.services.lightning-pool.enable = mkOption { type = types.bool; default = false; };
options.services.joinmarket.enable = mkOption { type = types.bool; default = false; };
options.services.joinmarket-ob-watcher.enable = mkOption { type = types.bool; default = false; };
}