2020-08-12 07:47:56 -07:00
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
|
|
|
|
with lib;
|
|
|
|
let
|
|
|
|
options.services = {
|
|
|
|
btcpayserver = {
|
2021-12-14 10:51:23 -08:00
|
|
|
enable = mkEnableOption "btcpayserver, a self-hosted Bitcoin payment processor";
|
2021-01-14 04:24:05 -08:00
|
|
|
address = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "127.0.0.1";
|
|
|
|
description = "Address to listen on.";
|
|
|
|
};
|
|
|
|
port = mkOption {
|
|
|
|
type = types.port;
|
|
|
|
default = 23000;
|
|
|
|
description = "Port to listen on.";
|
|
|
|
};
|
2020-08-12 07:47:56 -07:00
|
|
|
package = mkOption {
|
|
|
|
type = types.package;
|
2021-07-13 07:03:08 -07:00
|
|
|
default = if cfg.btcpayserver.lbtc then
|
2021-12-07 19:07:26 -08:00
|
|
|
config.nix-bitcoin.pkgs.btcpayserver.override { altcoinSupport = true; }
|
2021-07-13 07:03:08 -07:00
|
|
|
else
|
2021-12-07 19:07:26 -08:00
|
|
|
config.nix-bitcoin.pkgs.btcpayserver;
|
2021-12-07 19:07:28 -08:00
|
|
|
defaultText = "(See source)";
|
2020-08-12 07:47:56 -07:00
|
|
|
description = "The package providing btcpayserver binaries.";
|
|
|
|
};
|
|
|
|
dataDir = mkOption {
|
|
|
|
type = types.path;
|
|
|
|
default = "/var/lib/btcpayserver";
|
|
|
|
description = "The data directory for btcpayserver.";
|
|
|
|
};
|
|
|
|
lightningBackend = mkOption {
|
|
|
|
type = types.nullOr (types.enum [ "clightning" "lnd" ]);
|
|
|
|
default = null;
|
|
|
|
description = "The lightning node implementation to use.";
|
|
|
|
};
|
2021-07-13 07:03:08 -07:00
|
|
|
lbtc = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = "Enable liquid support in btcpayserver.";
|
|
|
|
};
|
2020-12-30 02:56:51 -08:00
|
|
|
rootpath = mkOption {
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
default = null;
|
|
|
|
example = "btcpayserver";
|
|
|
|
description = "The prefix for root-relative btcpayserver URLs.";
|
|
|
|
};
|
2021-09-13 04:40:48 -07:00
|
|
|
user = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "btcpayserver";
|
|
|
|
description = "The user as which to run btcpayserver.";
|
|
|
|
};
|
|
|
|
group = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = cfg.btcpayserver.user;
|
|
|
|
description = "The group as which to run btcpayserver.";
|
|
|
|
};
|
2021-11-28 12:24:49 -08:00
|
|
|
tor.enforce = nbLib.tor.enforce;
|
2020-08-12 07:47:56 -07:00
|
|
|
};
|
2021-11-26 06:13:32 -08:00
|
|
|
|
|
|
|
nbxplorer = {
|
|
|
|
enable = mkOption {
|
|
|
|
# This option is only used by netns-isolation
|
|
|
|
internal = true;
|
|
|
|
default = cfg.btcpayserver.enable;
|
|
|
|
description = ''
|
|
|
|
nbxplorer is always enabled when btcpayserver is enabled.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
package = mkOption {
|
|
|
|
type = types.package;
|
2021-12-07 19:07:26 -08:00
|
|
|
default = config.nix-bitcoin.pkgs.nbxplorer;
|
2021-12-07 19:07:28 -08:00
|
|
|
defaultText = "config.nix-bitcoin.pkgs.nbxplorer";
|
2021-11-26 06:13:32 -08:00
|
|
|
description = "The package providing nbxplorer binaries.";
|
|
|
|
};
|
|
|
|
address = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "127.0.0.1";
|
|
|
|
description = "Address to listen on.";
|
|
|
|
};
|
|
|
|
port = mkOption {
|
|
|
|
type = types.port;
|
|
|
|
default = 24444;
|
|
|
|
description = "Port to listen on.";
|
|
|
|
};
|
|
|
|
dataDir = mkOption {
|
|
|
|
type = types.path;
|
|
|
|
default = "/var/lib/nbxplorer";
|
|
|
|
description = "The data directory for nbxplorer.";
|
|
|
|
};
|
|
|
|
user = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "nbxplorer";
|
|
|
|
description = "The user as which to run nbxplorer.";
|
|
|
|
};
|
|
|
|
group = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = cfg.nbxplorer.user;
|
|
|
|
description = "The group as which to run nbxplorer.";
|
|
|
|
};
|
2021-11-28 12:24:49 -08:00
|
|
|
tor.enforce = nbLib.tor.enforce;
|
2021-11-26 06:13:32 -08:00
|
|
|
};
|
2020-08-12 07:47:56 -07:00
|
|
|
};
|
|
|
|
|
2021-09-13 04:40:47 -07:00
|
|
|
cfg = config.services;
|
|
|
|
nbLib = config.nix-bitcoin.lib;
|
2021-09-13 04:40:49 -07:00
|
|
|
|
2021-10-01 02:51:56 -07:00
|
|
|
inherit (config.services) bitcoind liquidd;
|
2021-09-13 04:40:47 -07:00
|
|
|
in {
|
|
|
|
inherit options;
|
|
|
|
|
2020-08-12 07:47:56 -07:00
|
|
|
config = mkIf cfg.btcpayserver.enable {
|
2021-10-01 02:51:58 -07:00
|
|
|
services.bitcoind = {
|
|
|
|
enable = true;
|
|
|
|
rpc.users.btcpayserver = {
|
|
|
|
passwordHMACFromFile = true;
|
|
|
|
rpcwhitelist = cfg.bitcoind.rpc.users.public.rpcwhitelist ++ [
|
|
|
|
"setban"
|
|
|
|
"generatetoaddress"
|
|
|
|
"getpeerinfo"
|
|
|
|
];
|
|
|
|
};
|
2021-10-29 08:56:57 -07:00
|
|
|
listenWhitelisted = true;
|
2021-10-01 02:51:58 -07:00
|
|
|
};
|
2020-10-18 05:49:20 -07:00
|
|
|
services.clightning.enable = mkIf (cfg.btcpayserver.lightningBackend == "clightning") true;
|
2021-10-30 05:55:55 -07:00
|
|
|
services.lnd = mkIf (cfg.btcpayserver.lightningBackend == "lnd") {
|
|
|
|
enable = true;
|
|
|
|
macaroons.btcpayserver = {
|
|
|
|
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"}'';
|
|
|
|
};
|
|
|
|
};
|
2021-10-01 02:51:58 -07:00
|
|
|
services.liquidd = mkIf cfg.btcpayserver.lbtc {
|
|
|
|
enable = true;
|
2021-10-29 08:56:57 -07:00
|
|
|
listenWhitelisted = true;
|
2021-02-01 13:53:22 -08:00
|
|
|
};
|
2020-09-17 01:04:23 -07:00
|
|
|
services.postgresql = {
|
|
|
|
enable = true;
|
2022-04-30 06:35:46 -07:00
|
|
|
ensureDatabases = [ "btcpaydb" "nbxplorer" ];
|
|
|
|
ensureUsers = [
|
|
|
|
{
|
|
|
|
name = cfg.btcpayserver.user;
|
|
|
|
ensurePermissions."DATABASE btcpaydb" = "ALL PRIVILEGES";
|
|
|
|
}
|
|
|
|
{
|
|
|
|
name = cfg.nbxplorer.user;
|
|
|
|
ensurePermissions."DATABASE nbxplorer" = "ALL PRIVILEGES";
|
|
|
|
}
|
|
|
|
];
|
2020-09-17 01:04:23 -07:00
|
|
|
};
|
|
|
|
|
2021-02-01 13:53:22 -08:00
|
|
|
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} - -"
|
|
|
|
];
|
|
|
|
|
2020-08-12 07:47:56 -07:00
|
|
|
systemd.services.nbxplorer = let
|
|
|
|
configFile = builtins.toFile "config" ''
|
2021-09-13 04:40:49 -07:00
|
|
|
network=${bitcoind.network}
|
2020-08-12 07:47:56 -07:00
|
|
|
btcrpcuser=${cfg.bitcoind.rpc.users.btcpayserver.name}
|
2021-10-01 02:51:57 -07:00
|
|
|
btcrpcurl=http://${nbLib.addressWithPort bitcoind.rpc.address cfg.bitcoind.rpc.port}
|
2021-10-29 08:56:57 -07:00
|
|
|
btcnodeendpoint=${nbLib.addressWithPort bitcoind.address bitcoind.whitelistedPort}
|
2021-01-14 04:24:05 -08:00
|
|
|
bind=${cfg.nbxplorer.address}
|
2020-10-16 08:43:11 -07:00
|
|
|
port=${toString cfg.nbxplorer.port}
|
2021-07-13 07:03:08 -07:00
|
|
|
${optionalString cfg.btcpayserver.lbtc ''
|
|
|
|
chains=btc,lbtc
|
2021-10-01 02:51:56 -07:00
|
|
|
lbtcrpcuser=${liquidd.rpcuser}
|
2021-10-01 02:51:57 -07:00
|
|
|
lbtcrpcurl=http://${nbLib.addressWithPort liquidd.rpc.address liquidd.rpc.port}
|
2021-11-01 04:59:05 -07:00
|
|
|
lbtcnodeendpoint=${nbLib.addressWithPort liquidd.address liquidd.whitelistedPort}
|
2021-07-13 07:03:08 -07:00
|
|
|
''}
|
2022-04-30 06:35:46 -07:00
|
|
|
postgres=User ID=${cfg.nbxplorer.user};Host=/run/postgresql;Database=nbxplorer
|
|
|
|
automigrate=1
|
2020-08-12 07:47:56 -07:00
|
|
|
'';
|
2021-11-02 05:07:38 -07:00
|
|
|
in rec {
|
2020-08-12 07:47:56 -07:00
|
|
|
wantedBy = [ "multi-user.target" ];
|
2022-04-30 06:35:46 -07:00
|
|
|
requires = [ "bitcoind.service" "postgresql.service" ] ++ optional cfg.btcpayserver.lbtc "liquidd.service";
|
2021-11-02 05:07:38 -07:00
|
|
|
after = requires;
|
2020-08-12 07:47:56 -07:00
|
|
|
preStart = ''
|
2021-02-01 13:53:21 -08:00
|
|
|
install -m 600 ${configFile} '${cfg.nbxplorer.dataDir}/settings.config'
|
2021-07-13 07:03:08 -07:00
|
|
|
{
|
|
|
|
echo "btcrpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-btcpayserver)"
|
|
|
|
${optionalString cfg.btcpayserver.lbtc ''
|
|
|
|
echo "lbtcrpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/liquid-rpcpassword)"
|
|
|
|
''}
|
|
|
|
} >> '${cfg.nbxplorer.dataDir}/settings.config'
|
2020-08-12 07:47:56 -07:00
|
|
|
'';
|
2021-02-03 13:44:41 -08:00
|
|
|
serviceConfig = nbLib.defaultHardening // {
|
2020-08-12 07:47:56 -07:00
|
|
|
ExecStart = ''
|
|
|
|
${cfg.nbxplorer.package}/bin/nbxplorer --conf=${cfg.nbxplorer.dataDir}/settings.config \
|
|
|
|
--datadir=${cfg.nbxplorer.dataDir}
|
|
|
|
'';
|
|
|
|
User = cfg.nbxplorer.user;
|
|
|
|
Restart = "on-failure";
|
|
|
|
RestartSec = "10s";
|
2022-05-07 11:34:21 -07:00
|
|
|
ReadWritePaths = [ cfg.nbxplorer.dataDir ];
|
2020-08-12 07:47:56 -07:00
|
|
|
MemoryDenyWriteExecute = "false";
|
2021-11-28 12:24:49 -08:00
|
|
|
} // nbLib.allowedIPAddresses cfg.nbxplorer.tor.enforce;
|
2020-08-12 07:47:56 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
systemd.services.btcpayserver = let
|
2021-11-26 06:13:29 -08:00
|
|
|
nbExplorerUrl = "http://${nbLib.addressWithPort cfg.nbxplorer.address cfg.nbxplorer.port}/";
|
2021-09-13 04:40:49 -07:00
|
|
|
nbExplorerCookie = "${cfg.nbxplorer.dataDir}/${bitcoind.makeNetworkName "Main" "RegTest"}/.cookie";
|
2020-08-12 07:47:56 -07:00
|
|
|
configFile = builtins.toFile "config" (''
|
2021-09-13 04:40:49 -07:00
|
|
|
network=${bitcoind.network}
|
2021-02-01 13:53:01 -08:00
|
|
|
bind=${cfg.btcpayserver.address}
|
|
|
|
port=${toString cfg.btcpayserver.port}
|
2021-08-04 15:49:00 -07:00
|
|
|
socksendpoint=${config.nix-bitcoin.torClientAddressWithPort}
|
2021-07-13 07:03:08 -07:00
|
|
|
btcexplorerurl=${nbExplorerUrl}
|
|
|
|
btcexplorercookiefile=${nbExplorerCookie}
|
2021-02-01 13:53:01 -08:00
|
|
|
postgres=User ID=${cfg.btcpayserver.user};Host=/run/postgresql;Database=btcpaydb
|
2021-11-26 06:13:29 -08:00
|
|
|
'' + optionalString (cfg.btcpayserver.rootpath != null) ''
|
|
|
|
rootpath=${cfg.btcpayserver.rootpath}
|
2020-08-12 07:47:56 -07:00
|
|
|
'' + optionalString (cfg.btcpayserver.lightningBackend == "clightning") ''
|
2022-06-03 14:39:36 -07:00
|
|
|
btclightning=type=clightning;server=unix:///${cfg.clightning.dataDir}/${bitcoind.makeNetworkName "bitcoin" "regtest"}/lightning-rpc
|
2021-07-13 07:03:08 -07:00
|
|
|
'' + optionalString cfg.btcpayserver.lbtc ''
|
|
|
|
chains=btc,lbtc
|
|
|
|
lbtcexplorerurl=${nbExplorerUrl}
|
|
|
|
lbtcexplorercookiefile=${nbExplorerCookie}
|
2020-08-12 07:47:56 -07:00
|
|
|
'');
|
|
|
|
lndConfig =
|
|
|
|
"btclightning=type=lnd-rest;" +
|
2021-01-14 04:24:03 -08:00
|
|
|
"server=https://${cfg.lnd.restAddress}:${toString cfg.lnd.restPort}/;" +
|
2020-08-12 07:47:56 -07:00
|
|
|
"macaroonfilepath=/run/lnd/btcpayserver.macaroon;" +
|
|
|
|
"certthumbprint=";
|
|
|
|
in let self = {
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
2021-02-01 13:53:00 -08:00
|
|
|
requires = [ "nbxplorer.service" "postgresql.service" ]
|
2020-08-12 07:47:56 -07:00
|
|
|
++ optional (cfg.btcpayserver.lightningBackend != null) "${cfg.btcpayserver.lightningBackend}.service";
|
|
|
|
after = self.requires;
|
|
|
|
preStart = ''
|
2021-02-01 13:53:21 -08:00
|
|
|
install -m 600 ${configFile} '${cfg.btcpayserver.dataDir}/settings.config'
|
2020-08-12 07:47:56 -07:00
|
|
|
${optionalString (cfg.btcpayserver.lightningBackend == "lnd") ''
|
|
|
|
{
|
2021-09-08 08:01:10 -07:00
|
|
|
echo -n "${lndConfig}"
|
2021-09-08 08:01:13 -07:00
|
|
|
${pkgs.openssl}/bin/openssl x509 -noout -fingerprint -sha256 -in ${config.services.lnd.certPath} \
|
2021-09-08 08:01:10 -07:00
|
|
|
| sed -e 's/.*=//;s/://g'
|
2021-02-01 13:53:21 -08:00
|
|
|
} >> '${cfg.btcpayserver.dataDir}/settings.config'
|
2020-08-12 07:47:56 -07:00
|
|
|
''}
|
|
|
|
'';
|
2021-02-03 13:44:41 -08:00
|
|
|
serviceConfig = nbLib.defaultHardening // {
|
2020-08-12 07:47:56 -07:00
|
|
|
ExecStart = ''
|
2021-10-01 02:51:56 -07:00
|
|
|
${cfg.btcpayserver.package}/bin/btcpayserver --conf='${cfg.btcpayserver.dataDir}/settings.config' \
|
|
|
|
--datadir='${cfg.btcpayserver.dataDir}'
|
2020-08-12 07:47:56 -07:00
|
|
|
'';
|
|
|
|
User = cfg.btcpayserver.user;
|
|
|
|
Restart = "on-failure";
|
|
|
|
RestartSec = "10s";
|
2022-05-07 11:34:21 -07:00
|
|
|
ReadWritePaths = [ cfg.btcpayserver.dataDir ];
|
2020-08-12 07:47:56 -07:00
|
|
|
MemoryDenyWriteExecute = "false";
|
2021-11-28 12:24:49 -08:00
|
|
|
} // nbLib.allowedIPAddresses cfg.btcpayserver.tor.enforce;
|
2020-08-12 07:47:56 -07:00
|
|
|
}; in self;
|
|
|
|
|
|
|
|
users.users.${cfg.nbxplorer.user} = {
|
2021-08-04 15:48:59 -07:00
|
|
|
isSystemUser = true;
|
2020-08-12 07:47:56 -07:00
|
|
|
group = cfg.nbxplorer.group;
|
2021-07-13 07:03:08 -07:00
|
|
|
extraGroups = [ "bitcoinrpc-public" ]
|
2021-10-01 02:51:56 -07:00
|
|
|
++ optional cfg.btcpayserver.lbtc liquidd.group;
|
2020-08-12 07:47:56 -07:00
|
|
|
home = cfg.nbxplorer.dataDir;
|
|
|
|
};
|
|
|
|
users.groups.${cfg.nbxplorer.group} = {};
|
|
|
|
users.users.${cfg.btcpayserver.user} = {
|
2021-08-04 15:48:59 -07:00
|
|
|
isSystemUser = true;
|
2020-08-12 07:47:56 -07:00
|
|
|
group = cfg.btcpayserver.group;
|
2021-02-16 08:52:45 -08:00
|
|
|
extraGroups = [ cfg.nbxplorer.group ]
|
2020-08-12 07:47:56 -07:00
|
|
|
++ optional (cfg.btcpayserver.lightningBackend == "clightning") cfg.clightning.user;
|
|
|
|
home = cfg.btcpayserver.dataDir;
|
|
|
|
};
|
|
|
|
users.groups.${cfg.btcpayserver.group} = {};
|
|
|
|
|
2021-02-01 13:53:22 -08:00
|
|
|
nix-bitcoin.secrets = {
|
|
|
|
bitcoin-rpcpassword-btcpayserver = {
|
2021-02-16 08:52:45 -08:00
|
|
|
user = cfg.bitcoind.user;
|
|
|
|
group = cfg.nbxplorer.group;
|
2021-02-01 13:53:22 -08:00
|
|
|
};
|
2021-02-16 08:52:45 -08:00
|
|
|
bitcoin-HMAC-btcpayserver.user = cfg.bitcoind.user;
|
2020-08-12 07:47:56 -07:00
|
|
|
};
|
2021-09-08 08:01:18 -07:00
|
|
|
nix-bitcoin.generateSecretsCmds.btcpayserver = ''
|
|
|
|
makeBitcoinRPCPassword btcpayserver
|
|
|
|
'';
|
2020-08-12 07:47:56 -07:00
|
|
|
};
|
|
|
|
}
|