joinmarket: add module
This commit is contained in:
parent
263525d724
commit
173891fa5b
|
@ -172,6 +172,16 @@
|
||||||
# and electrs data directory, enable
|
# and electrs data directory, enable
|
||||||
# services.backups.with-bulk-data = true;
|
# services.backups.with-bulk-data = true;
|
||||||
|
|
||||||
|
### JOINMARKET
|
||||||
|
# Enable this module to allow using JoinMarket's user interactive scripts (including
|
||||||
|
# tumbler.py).
|
||||||
|
# Note: JoinMarket has full access to bitcoind, including its wallet functionality.
|
||||||
|
# services.joinmarket.enable = true;
|
||||||
|
# Enable this option to enable the JoinMarket Yield Generator Bot. You will be able to
|
||||||
|
# earn sats by providing CoinJoin liquidity. This makes it impossible to use other
|
||||||
|
# scripts that access your wallet.
|
||||||
|
# services.joinmarket.yieldgenerator.enable = true;
|
||||||
|
|
||||||
# FIXME: Define your hostname.
|
# FIXME: Define your hostname.
|
||||||
networking.hostName = "nix-bitcoin";
|
networking.hostName = "nix-bitcoin";
|
||||||
time.timeZone = "UTC";
|
time.timeZone = "UTC";
|
||||||
|
|
|
@ -12,4 +12,5 @@
|
||||||
spark-wallet = ./spark-wallet.nix;
|
spark-wallet = ./spark-wallet.nix;
|
||||||
recurring-donations = ./recurring-donations.nix;
|
recurring-donations = ./recurring-donations.nix;
|
||||||
lnd = ./lnd.nix;
|
lnd = ./lnd.nix;
|
||||||
|
joinmarket = ./joinmarket.nix;
|
||||||
}
|
}
|
||||||
|
|
202
modules/joinmarket.nix
Normal file
202
modules/joinmarket.nix
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.joinmarket;
|
||||||
|
inherit (config) nix-bitcoin-services;
|
||||||
|
secretsDir = config.nix-bitcoin.secretsDir;
|
||||||
|
|
||||||
|
torAddress = builtins.head (builtins.split ":" config.services.tor.client.socksListenAddress);
|
||||||
|
configFile = builtins.toFile "config" ''
|
||||||
|
# Based on https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/jmclient/jmclient/configure.py
|
||||||
|
[DAEMON]
|
||||||
|
no_daemon = 0
|
||||||
|
daemon_port = 27183
|
||||||
|
daemon_host = localhost
|
||||||
|
use_ssl = false
|
||||||
|
|
||||||
|
[BLOCKCHAIN]
|
||||||
|
blockchain_source = bitcoin-rpc
|
||||||
|
network = mainnet
|
||||||
|
rpc_host = ${builtins.elemAt config.services.bitcoind.rpcbind 0}
|
||||||
|
rpc_port = 8332
|
||||||
|
rpc_user = ${config.services.bitcoind.rpc.users.privileged.name}
|
||||||
|
@@RPC_PASSWORD@@
|
||||||
|
|
||||||
|
[MESSAGING:server1]
|
||||||
|
host = darksci3bfoka7tw.onion
|
||||||
|
channel = joinmarket-pit
|
||||||
|
port = 6697
|
||||||
|
usessl = true
|
||||||
|
socks5 = true
|
||||||
|
socks5_host = ${torAddress}
|
||||||
|
socks5_port = 9050
|
||||||
|
|
||||||
|
[MESSAGING:server2]
|
||||||
|
host = ncwkrwxpq2ikcngxq3dy2xctuheniggtqeibvgofixpzvrwpa77tozqd.onion
|
||||||
|
channel = joinmarket-pit
|
||||||
|
port = 6667
|
||||||
|
usessl = false
|
||||||
|
socks5 = true
|
||||||
|
socks5_host = ${torAddress}
|
||||||
|
socks5_port = 9050
|
||||||
|
|
||||||
|
[LOGGING]
|
||||||
|
console_log_level = INFO
|
||||||
|
color = false
|
||||||
|
|
||||||
|
[POLICY]
|
||||||
|
segwit = true
|
||||||
|
native = false
|
||||||
|
merge_algorithm = default
|
||||||
|
tx_fees = 3
|
||||||
|
absurd_fee_per_kb = 350000
|
||||||
|
tx_broadcast = self
|
||||||
|
minimum_makers = 4
|
||||||
|
max_sats_freeze_reuse = -1
|
||||||
|
taker_utxo_retries = 3
|
||||||
|
taker_utxo_age = 5
|
||||||
|
taker_utxo_amtpercent = 20
|
||||||
|
accept_commitment_broadcasts = 1
|
||||||
|
commit_file_location = cmtdata/commitments.json
|
||||||
|
'';
|
||||||
|
|
||||||
|
# The jm scripts create a 'logs' dir in the working dir,
|
||||||
|
# so run them inside dataDir.
|
||||||
|
cli = pkgs.runCommand "joinmarket-cli" {} ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
jm=${pkgs.nix-bitcoin.joinmarket}/bin
|
||||||
|
cd $jm
|
||||||
|
for bin in jm-*; do
|
||||||
|
{
|
||||||
|
echo "#!${pkgs.bash}/bin/bash";
|
||||||
|
echo "cd '${cfg.dataDir}' && ${cfg.cliExec} sudo -u ${cfg.user} $jm/$bin --datadir='${cfg.dataDir}' \"\$@\"";
|
||||||
|
} > $out/bin/$bin
|
||||||
|
done
|
||||||
|
chmod -R +x $out/bin
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
options.services.joinmarket = {
|
||||||
|
enable = mkEnableOption "JoinMarket";
|
||||||
|
yieldgenerator = {
|
||||||
|
enable = mkEnableOption "yield generator bot";
|
||||||
|
customParameters = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "";
|
||||||
|
example = ''
|
||||||
|
txfee = 200
|
||||||
|
cjfee_a = 300
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
Python code to define custom yield generator parameters, as described in
|
||||||
|
https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/YIELDGENERATOR.md
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
dataDir = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "/var/lib/joinmarket";
|
||||||
|
description = "The data directory for JoinMarket.";
|
||||||
|
};
|
||||||
|
user = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "joinmarket";
|
||||||
|
description = "The user as which to run JoinMarket.";
|
||||||
|
};
|
||||||
|
group = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = cfg.user;
|
||||||
|
description = "The group as which to run JoinMarket.";
|
||||||
|
};
|
||||||
|
cli = mkOption {
|
||||||
|
default = cli;
|
||||||
|
};
|
||||||
|
inherit (nix-bitcoin-services) cliExec;
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable (mkMerge [{
|
||||||
|
environment.systemPackages = [
|
||||||
|
(hiPrio cfg.cli)
|
||||||
|
];
|
||||||
|
users.users.${cfg.user} = {
|
||||||
|
description = "joinmarket User";
|
||||||
|
group = "${cfg.group}";
|
||||||
|
home = cfg.dataDir;
|
||||||
|
};
|
||||||
|
users.groups.${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;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.joinmarket = {
|
||||||
|
description = "JoinMarket Daemon";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
requires = [ "bitcoind.service" ];
|
||||||
|
after = [ "bitcoind.service" ];
|
||||||
|
serviceConfig = nix-bitcoin-services.defaultHardening // {
|
||||||
|
ExecStartPre = nix-bitcoin-services.privileged ''
|
||||||
|
install -o '${cfg.user}' -g '${cfg.group}' -m 640 ${configFile} ${cfg.dataDir}/joinmarket.cfg
|
||||||
|
sed -i \
|
||||||
|
"s|@@RPC_PASSWORD@@|rpc_password = $(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-privileged)|" \
|
||||||
|
'${cfg.dataDir}/joinmarket.cfg'
|
||||||
|
'';
|
||||||
|
ExecStart = "${pkgs.nix-bitcoin.joinmarket}/bin/joinmarketd";
|
||||||
|
WorkingDirectory = "${cfg.dataDir}"; # The service creates 'commitmentlist' in the working dir
|
||||||
|
User = "${cfg.user}";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = "10s";
|
||||||
|
ReadWritePaths = "${cfg.dataDir}";
|
||||||
|
} // nix-bitcoin-services.allowTor;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
(mkIf cfg.yieldgenerator.enable {
|
||||||
|
nix-bitcoin.secrets.jm-wallet-password.user = cfg.user;
|
||||||
|
|
||||||
|
systemd.services.joinmarket-yieldgenerator = let
|
||||||
|
ygDefault = "${pkgs.nix-bitcoin.joinmarket}/bin/jm-yg-privacyenhanced";
|
||||||
|
ygBinary = if cfg.yieldgenerator.customParameters == "" then
|
||||||
|
ygDefault
|
||||||
|
else
|
||||||
|
pkgs.runCommand "jm-yieldgenerator-custom" {
|
||||||
|
inherit (cfg.yieldgenerator) customParameters;
|
||||||
|
} ''
|
||||||
|
substitute ${ygDefault} $out \
|
||||||
|
--replace "# end of settings customization" "$customParameters"
|
||||||
|
chmod +x $out
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
description = "CoinJoin maker bot to gain privacy and passively generate income";
|
||||||
|
wantedBy = [ "joinmarket.service" ];
|
||||||
|
requires = [ "joinmarket.service" ];
|
||||||
|
after = [ "joinmarket.service" ];
|
||||||
|
preStart = let
|
||||||
|
start = ''
|
||||||
|
exec ${ygBinary} --datadir='${cfg.dataDir}' --wallet-password-stdin wallet.jmdat
|
||||||
|
'';
|
||||||
|
in ''
|
||||||
|
pw=$(cat "${secretsDir}"/jm-wallet-password)
|
||||||
|
echo "echo -n $pw | ${start}" > $RUNTIME_DIRECTORY/start
|
||||||
|
'';
|
||||||
|
serviceConfig = nix-bitcoin-services.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
|
||||||
|
ExecStart = "${pkgs.bash}/bin/bash /run/${RuntimeDirectory}/start";
|
||||||
|
User = "${cfg.user}";
|
||||||
|
ReadWritePaths = "${cfg.dataDir}";
|
||||||
|
} // nix-bitcoin-services.allowTor;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
}
|
|
@ -19,6 +19,7 @@
|
||||||
./security.nix
|
./security.nix
|
||||||
./backups.nix
|
./backups.nix
|
||||||
./btcpayserver.nix
|
./btcpayserver.nix
|
||||||
|
./joinmarket.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
disabledModules = [ "services/networking/bitcoind.nix" ];
|
disabledModules = [ "services/networking/bitcoind.nix" ];
|
||||||
|
|
|
@ -131,6 +131,7 @@ in {
|
||||||
${ip} link del nb-br
|
${ip} link del nb-br
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
} //
|
} //
|
||||||
(let
|
(let
|
||||||
makeNetnsServices = n: v: let
|
makeNetnsServices = n: v: let
|
||||||
|
@ -242,6 +243,10 @@ in {
|
||||||
++ optional (config.services.btcpayserver.lightningBackend == "lnd") "lnd";
|
++ optional (config.services.btcpayserver.lightningBackend == "lnd") "lnd";
|
||||||
# communicates with clightning over rpc socket
|
# communicates with clightning over rpc socket
|
||||||
};
|
};
|
||||||
|
joinmarket = {
|
||||||
|
id = 25;
|
||||||
|
connections = [ "bitcoind" ];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.bitcoind = {
|
services.bitcoind = {
|
||||||
|
@ -314,6 +319,9 @@ in {
|
||||||
|
|
||||||
services.nbxplorer.bind = netns.nbxplorer.address;
|
services.nbxplorer.bind = netns.nbxplorer.address;
|
||||||
services.btcpayserver.bind = netns.btcpayserver.address;
|
services.btcpayserver.bind = netns.btcpayserver.address;
|
||||||
|
|
||||||
|
services.joinmarket.cliExec = mkCliExec "joinmarket";
|
||||||
|
systemd.services.joinmarket-yieldgenerator.serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-joinmarket";
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,8 @@ in {
|
||||||
++ (optionals cfg.lnd.enable [ "lnd" ])
|
++ (optionals cfg.lnd.enable [ "lnd" ])
|
||||||
++ (optionals cfg.liquidd.enable [ cfg.liquidd.group ])
|
++ (optionals cfg.liquidd.enable [ cfg.liquidd.group ])
|
||||||
++ (optionals (cfg.hardware-wallets.ledger || cfg.hardware-wallets.trezor)
|
++ (optionals (cfg.hardware-wallets.ledger || cfg.hardware-wallets.trezor)
|
||||||
[ cfg.hardware-wallets.group ]);
|
[ cfg.hardware-wallets.group ])
|
||||||
|
++ (optionals cfg.joinmarket.enable [ cfg.joinmarket.group ]);
|
||||||
openssh.authorizedKeys.keys = config.users.users.root.openssh.authorizedKeys.keys;
|
openssh.authorizedKeys.keys = config.users.users.root.openssh.authorizedKeys.keys;
|
||||||
};
|
};
|
||||||
nix-bitcoin.netns-isolation.allowedUser = operatorName;
|
nix-bitcoin.netns-isolation.allowedUser = operatorName;
|
||||||
|
@ -182,6 +183,9 @@ in {
|
||||||
security.sudo.configFile =
|
security.sudo.configFile =
|
||||||
(optionalString cfg.lnd.enable ''
|
(optionalString cfg.lnd.enable ''
|
||||||
${operatorName} ALL=(lnd) NOPASSWD: ALL
|
${operatorName} ALL=(lnd) NOPASSWD: ALL
|
||||||
|
'') +
|
||||||
|
(optionalString cfg.joinmarket.enable ''
|
||||||
|
${operatorName} ALL=(${cfg.joinmarket.user}) NOPASSWD: ALL
|
||||||
'');
|
'');
|
||||||
|
|
||||||
# Enable nixops ssh for operator (`nixops ssh operator@mynode`) on nixops-vbox deployments
|
# Enable nixops ssh for operator (`nixops ssh operator@mynode`) on nixops-vbox deployments
|
||||||
|
|
|
@ -18,6 +18,7 @@ makePasswordSecret liquid-rpcpassword
|
||||||
makePasswordSecret lightning-charge-token
|
makePasswordSecret lightning-charge-token
|
||||||
makePasswordSecret spark-wallet-password
|
makePasswordSecret spark-wallet-password
|
||||||
makePasswordSecret backup-encryption-password
|
makePasswordSecret backup-encryption-password
|
||||||
|
touch jm-wallet-password
|
||||||
|
|
||||||
[[ -e bitcoin-HMAC-privileged ]] || makeHMAC privileged
|
[[ -e bitcoin-HMAC-privileged ]] || makeHMAC privileged
|
||||||
[[ -e bitcoin-HMAC-public ]] || makeHMAC public
|
[[ -e bitcoin-HMAC-public ]] || makeHMAC public
|
||||||
|
|
|
@ -13,7 +13,8 @@ static char *allowed_netns[] = {
|
||||||
"nb-lnd",
|
"nb-lnd",
|
||||||
"nb-lightning-loop",
|
"nb-lightning-loop",
|
||||||
"nb-bitcoind",
|
"nb-bitcoind",
|
||||||
"nb-liquidd"
|
"nb-liquidd",
|
||||||
|
"nb-joinmarket"
|
||||||
};
|
};
|
||||||
|
|
||||||
int is_netns_allowed(char *netns) {
|
int is_netns_allowed(char *netns) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user