2021-09-13 11:40:46 +00:00
|
|
|
{ config, lib, pkgs, ... }:
|
2021-06-02 01:11:26 +00:00
|
|
|
|
|
|
|
with lib;
|
|
|
|
let
|
|
|
|
options.services.charge-lnd = with types; {
|
|
|
|
enable = mkEnableOption "charge-lnd, policy-based fee manager";
|
|
|
|
|
|
|
|
extraFlags = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [];
|
|
|
|
example = [ "--verbose" "--dry-run" ];
|
2022-12-18 12:13:47 +00:00
|
|
|
description = mdDoc "Extra flags to pass to the charge-lnd command.";
|
2021-06-02 01:11:26 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
interval = mkOption {
|
|
|
|
type = str;
|
|
|
|
default = "*-*-* 04:00:00";
|
|
|
|
example = "hourly";
|
2022-12-18 12:13:47 +00:00
|
|
|
description = mdDoc ''
|
2021-06-02 01:11:26 +00:00
|
|
|
Systemd calendar expression when to adjust fees.
|
|
|
|
|
2022-12-18 12:13:47 +00:00
|
|
|
See {man}`systemd.time(7)` for possible values.
|
2021-06-02 01:11:26 +00:00
|
|
|
|
|
|
|
Default is once a day.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
randomDelay = mkOption {
|
|
|
|
type = str;
|
|
|
|
default = "1h";
|
2022-12-18 12:13:47 +00:00
|
|
|
description = mdDoc ''
|
2021-06-02 01:11:26 +00:00
|
|
|
Random delay to add to scheduled time.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
policies = mkOption {
|
|
|
|
type = types.lines;
|
|
|
|
default = "";
|
2021-12-14 18:51:18 +00:00
|
|
|
example = ''
|
2021-06-02 01:11:26 +00:00
|
|
|
[discourage-routing-out-of-balance]
|
|
|
|
chan.max_ratio = 0.1
|
|
|
|
chan.min_capacity = 250000
|
|
|
|
strategy = static
|
|
|
|
base_fee_msat = 10000
|
|
|
|
fee_ppm = 500
|
|
|
|
|
|
|
|
[encourage-routing-to-balance]
|
|
|
|
chan.min_ratio = 0.9
|
|
|
|
chan.min_capacity = 250000
|
|
|
|
strategy = static
|
|
|
|
base_fee_msat = 1
|
|
|
|
fee_ppm = 2
|
|
|
|
|
|
|
|
[default]
|
|
|
|
strategy = ignore
|
|
|
|
'';
|
2022-12-18 12:13:47 +00:00
|
|
|
description = mdDoc ''
|
2021-06-02 01:11:26 +00:00
|
|
|
Policy definitions in INI format.
|
|
|
|
|
|
|
|
See https://github.com/accumulator/charge-lnd/blob/master/README.md#usage
|
|
|
|
for possible properties and parameters.
|
|
|
|
|
|
|
|
Policies are evaluated from top to bottom.
|
|
|
|
The first matching policy (or `default`) is applied.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2021-09-13 11:40:47 +00:00
|
|
|
cfg = config.services.charge-lnd;
|
|
|
|
nbLib = config.nix-bitcoin.lib;
|
2021-09-13 11:40:49 +00:00
|
|
|
|
2021-09-13 11:40:47 +00:00
|
|
|
lnd = config.services.lnd;
|
|
|
|
electrs = if (config.services ? electrs) && config.services.electrs.enable
|
|
|
|
then config.services.electrs
|
|
|
|
else null;
|
|
|
|
|
|
|
|
user = "charge-lnd";
|
|
|
|
group = user;
|
|
|
|
dataDir = "/var/lib/charge-lnd";
|
|
|
|
configFile = builtins.toFile "charge-lnd.config" cfg.policies;
|
|
|
|
checkedConfig = pkgs.runCommandNoCC "charge-lnd-checked.config" { } ''
|
|
|
|
${config.nix-bitcoin.pkgs.charge-lnd}/bin/charge-lnd --check --config ${configFile}
|
|
|
|
cp ${configFile} $out
|
|
|
|
'';
|
|
|
|
in
|
|
|
|
{
|
|
|
|
inherit options;
|
|
|
|
|
2021-06-02 01:11:26 +00:00
|
|
|
config = mkIf cfg.enable {
|
|
|
|
services.lnd = {
|
|
|
|
enable = true;
|
|
|
|
macaroons.charge-lnd = {
|
|
|
|
user = user;
|
|
|
|
permissions = ''{"entity":"info","action":"read"},{"entity":"onchain","action":"read"},{"entity":"offchain","action":"read"},{"entity":"offchain","action":"write"}'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
systemd.services.charge-lnd = {
|
|
|
|
documentation = [ "https://github.com/accumulator/charge-lnd/blob/master/README.md" ];
|
|
|
|
after = [ "lnd.service" ];
|
|
|
|
requires = [ "lnd.service" ];
|
|
|
|
# lnd's data directory (--lnddir) is not accessible to charge-lnd.
|
|
|
|
# Instead use directory "lnddir-proxy" as lnddir and link relevant files to it.
|
|
|
|
preStart = ''
|
|
|
|
macaroonDir=${dataDir}/lnddir-proxy/data/chain/bitcoin/mainnet
|
|
|
|
mkdir -p $macaroonDir
|
|
|
|
ln -sf /run/lnd/charge-lnd.macaroon $macaroonDir
|
2021-09-08 15:01:13 +00:00
|
|
|
ln -sf ${lnd.certPath} ${dataDir}/lnddir-proxy/tls.cert
|
2021-06-02 01:11:26 +00:00
|
|
|
'';
|
|
|
|
serviceConfig = nbLib.defaultHardening // {
|
|
|
|
ExecStart = ''
|
|
|
|
${config.nix-bitcoin.pkgs.charge-lnd}/bin/charge-lnd \
|
|
|
|
--lnddir ${dataDir}/lnddir-proxy \
|
2021-10-01 09:51:57 +00:00
|
|
|
--grpc ${nbLib.addressWithPort lnd.rpcAddress lnd.rpcPort} \
|
2021-06-02 01:11:26 +00:00
|
|
|
--config ${checkedConfig} \
|
2021-10-01 09:51:57 +00:00
|
|
|
${optionalString (electrs != null)
|
|
|
|
"--electrum-server ${nbLib.addressWithPort electrs.address electrs.port}"} \
|
2021-06-02 01:11:26 +00:00
|
|
|
${escapeShellArgs cfg.extraFlags}
|
|
|
|
'';
|
|
|
|
Type = "oneshot";
|
|
|
|
User = user;
|
|
|
|
Group = group;
|
|
|
|
StateDirectory = "charge-lnd";
|
|
|
|
} // nbLib.allowLocalIPAddresses;
|
|
|
|
};
|
|
|
|
|
|
|
|
systemd.timers.charge-lnd = {
|
|
|
|
wantedBy = [ "timers.target" ];
|
|
|
|
timerConfig = {
|
|
|
|
OnCalendar = cfg.interval;
|
|
|
|
RandomizedDelaySec = cfg.randomDelay;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
users.users.${user} = {
|
|
|
|
isSystemUser = true;
|
2021-08-04 22:48:59 +00:00
|
|
|
group = group;
|
2021-06-02 01:11:26 +00:00
|
|
|
};
|
|
|
|
users.groups.${group} = {};
|
|
|
|
};
|
|
|
|
}
|