Merge #107: Add LND support

9d029fd1af Remove lnd explicit tor onion service config (Ștefan D. Mihăilă)
1f407ef22c Remove lnd user from onion-chef (Ștefan D. Mihăilă)
5880023158 Increase xxd column size (Ștefan D. Mihăilă)
101ae3c370 Instruct user to backup channel.backup (Ștefan D. Mihăilă)
fccd91972a Fix "value is a list [...]" error when lnd is not enabled (Ștefan D. Mihăilă)
700fdf6feb Add logdir and tor.privatekeypath to lnd.conf (Ștefan D. Mihăilă)
5a2517b926 Check for existing secrets and create them  more granularly (Ștefan D. Mihăilă)
d6f961db89 Reuse lnd seed (Ștefan D. Mihăilă)
9b0753135c Add LND support (Ștefan D. Mihăilă)
4acf5cd32c Remove unused nginx.csr file (Ștefan D. Mihăilă)
19b971f21f Rename nginx certificate files (Ștefan D. Mihăilă)

Pull request description:

ACKs for top commit:
  jonasnick:
    ACK 9d029fd1af

Tree-SHA512: 58ee80bcab6c3a1c4642a5d40b94e10d28311557ae7c69539fee90d6f252a6afc70b8066cc7d7ddc0a45e2675978718a369b0341c518f8ce7590cbde1403eaeb
This commit is contained in:
Jonas Nick 2019-08-31 15:21:30 +00:00
commit e4d2aab561
No known key found for this signature in database
GPG key ID: 4861DBF262123605
11 changed files with 295 additions and 38 deletions

View file

@ -193,6 +193,18 @@ in {
to stay under the specified target size in MiB)
'';
};
zmqpubrawblock = mkOption {
type = types.nullOr types.string;
default = null;
example = "tcp://127.0.0.1:28332";
description = "ZMQ address for zmqpubrawblock notifications";
};
zmqpubrawtx = mkOption {
type = types.nullOr types.string;
default = null;
example = "tcp://127.0.0.1:28333";
description = "ZMQ address for zmqpubrawtx notifications";
};
enforceTor = nix-bitcoin-services.enforceTor;
};
};
@ -239,7 +251,7 @@ in {
// (if cfg.enforceTor
then nix-bitcoin-services.allowTor
else nix-bitcoin-services.allowAnyIP
);
) // optionalAttrs config.services.lnd.enable nix-bitcoin-services.allowAnyProtocol; # FOR ZMQ
};
systemd.services.bitcoind-import-banlist = {
description = "Bitcoin daemon banlist importer";

View file

@ -11,4 +11,5 @@
nix-bitcoin-webindex = ./nix-bitcoin-webindex.nix;
spark-wallet = ./spark-wallet.nix;
recurring-donations = ./recurring-donations.nix;
lnd = ./lnd.nix;
}

View file

@ -106,8 +106,8 @@ in {
listen ${toString config.services.electrs.nginxport} ssl;
proxy_pass electrs;
ssl_certificate /secrets/ssl_certificate;
ssl_certificate_key /secrets/ssl_certificate_key;
ssl_certificate /secrets/nginx_cert;
ssl_certificate_key /secrets/nginx_key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 4h;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

132
modules/lnd.nix Normal file
View file

@ -0,0 +1,132 @@
{ config, lib, pkgs, ... }:
with lib;
let
nix-bitcoin-services = pkgs.callPackage ./nix-bitcoin-services.nix { };
cfg = config.services.lnd;
configFile = pkgs.writeText "lnd.conf" ''
datadir=${cfg.dataDir}
logdir=${cfg.dataDir}/logs
bitcoin.mainnet=1
tlscertpath=/secrets/lnd_cert
tlskeypath=/secrets/lnd_key
bitcoin.active=1
bitcoin.node=bitcoind
tor.active=true
tor.v3=true
tor.streamisolation=true
tor.privatekeypath=${cfg.dataDir}/v3_onion_private_key
bitcoind.rpcuser=${config.services.bitcoind.rpcuser}
bitcoind.zmqpubrawblock=${config.services.bitcoind.zmqpubrawblock}
bitcoind.zmqpubrawtx=${config.services.bitcoind.zmqpubrawtx}
${cfg.extraConfig}
'';
init-lnd-wallet-script = pkgs.writeScript "init-lnd-wallet.sh" ''
#!/bin/sh
set -e
umask 377
${pkgs.coreutils}/bin/sleep 5
if [ ! -f /secrets/lnd-seed-mnemonic ]
then
${pkgs.coreutils}/bin/echo Creating lnd seed
${pkgs.curl}/bin/curl -s \
--cacert /secrets/lnd_cert \
-X GET https://127.0.0.1:8080/v1/genseed | ${pkgs.jq}/bin/jq -c '.cipher_seed_mnemonic' > /secrets/lnd-seed-mnemonic
fi
if [ ! -f ${cfg.dataDir}/chain/bitcoin/mainnet/wallet.db ]
then
${pkgs.coreutils}/bin/echo Creating lnd wallet
${pkgs.curl}/bin/curl -s \
--cacert /secrets/lnd_cert \
-X POST -d "{\"wallet_password\": \"$(${pkgs.coreutils}/bin/cat /secrets/lnd-wallet-password | ${pkgs.coreutils}/bin/tr -d '\n' | ${pkgs.coreutils}/bin/base64 -w0)\", \
\"cipher_seed_mnemonic\": $(${pkgs.coreutils}/bin/cat /secrets/lnd-seed-mnemonic | ${pkgs.coreutils}/bin/tr -d '\n')}" \
https://127.0.0.1:8080/v1/initwallet
else
${pkgs.coreutils}/bin/echo Unlocking lnd wallet
${pkgs.curl}/bin/curl -s \
-H "Grpc-Metadata-macaroon: $(${pkgs.xxd}/bin/xxd -ps -u -c 99999 ${cfg.dataDir}/chain/bitcoin/mainnet/admin.macaroon)" \
--cacert /secrets/lnd_cert \
-X POST \
-d "{\"wallet_password\": \"$(${pkgs.coreutils}/bin/cat /secrets/lnd-wallet-password | ${pkgs.coreutils}/bin/tr -d '\n' | ${pkgs.coreutils}/bin/base64 -w0)\"}" \
https://127.0.0.1:8080/v1/unlockwallet
fi
exit 0
'';
in {
options.services.lnd = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
If enabled, the LND service will be installed.
'';
};
dataDir = mkOption {
type = types.path;
default = "/var/lib/lnd";
description = "The data directory for LND.";
};
extraConfig = mkOption {
type = types.lines;
default = "";
example = ''
autopilot.active=1
'';
description = "Additional configurations to be appended to <filename>lnd.conf</filename>.";
};
enforceTor = nix-bitcoin-services.enforceTor;
};
config = mkIf cfg.enable {
users.users.lnd = {
description = "LND User";
group = "lnd";
extraGroups = [ "bitcoinrpc" "keys" ];
home = cfg.dataDir;
};
users.groups.lnd = {
name = "lnd";
};
systemd.services.lnd = {
description = "Run LND";
path = [ pkgs.altcoins.bitcoind ];
wantedBy = [ "multi-user.target" ];
requires = [ "bitcoind.service" ];
after = [ "bitcoind.service" ];
preStart = ''
mkdir -m 0770 -p ${cfg.dataDir}
cp ${configFile} ${cfg.dataDir}/lnd.conf
chown -R 'lnd:lnd' '${cfg.dataDir}'
chmod u=rw,g=r,o= ${cfg.dataDir}/lnd.conf
echo "bitcoind.rpcpass=$(cat /secrets/bitcoin-rpcpassword)" >> '${cfg.dataDir}/lnd.conf'
'';
serviceConfig = {
PermissionsStartOnly = "true";
ExecStart = "${pkgs.lnd}/bin/lnd --configfile=${cfg.dataDir}/lnd.conf";
ExecStartPost = "${pkgs.bash}/bin/bash ${init-lnd-wallet-script}";
User = "lnd";
Restart = "on-failure";
RestartSec = "10s";
} // nix-bitcoin-services.defaultHardening
// (if cfg.enforceTor
then nix-bitcoin-services.allowTor
else nix-bitcoin-services.allowAnyIP
) // nix-bitcoin-services.allowAnyProtocol; # For ZMQ
};
};
}

View file

@ -15,5 +15,6 @@ in {
bitcoin = nixpkgs-unstable.bitcoin.override { miniupnpc = null; };
altcoins.bitcoind = nixpkgs-unstable.altcoins.bitcoind.override { miniupnpc = null; };
clightning = nixpkgs-unstable.clightning.override { };
lnd = nixpkgs-unstable.lnd.override { };
};
}

View file

@ -28,6 +28,7 @@ in {
./onion-chef.nix
./recurring-donations.nix
./hardware-wallets.nix
./lnd.nix
];
options.services.nix-bitcoin = {
@ -46,6 +47,8 @@ in {
# Tor
services.tor.enable = true;
services.tor.client.enable = true;
# LND uses ControlPort to create onion services
services.tor.controlPort = if config.services.lnd.enable then 9051 else null;
# Tor SSH service
services.tor.hiddenServices.sshd = {
@ -64,12 +67,16 @@ in {
services.bitcoind.enforceTor = true;
services.bitcoind.port = 8333;
services.bitcoind.rpcuser = "bitcoinrpc";
services.bitcoind.zmqpubrawblock = "tcp://127.0.0.1:28332";
services.bitcoind.zmqpubrawtx = "tcp://127.0.0.1:28333";
services.bitcoind.extraConfig = ''
assumevalid=0000000000000000000726d186d6298b5054b9a5c49639752294b322a305d240
addnode=ecoc5q34tmbq54wl.onion
discover=0
addresstype=bech32
changetype=bech32
${optionalString (config.services.lnd.enable) "zmqpubrawblock=${config.services.bitcoind.zmqpubrawblock}"}
${optionalString (config.services.lnd.enable) "zmqpubrawtx=${config.services.bitcoind.zmqpubrawtx}"}
'';
services.bitcoind.prune = 0;
services.bitcoind.dbCache = 1000;
@ -96,11 +103,15 @@ in {
version = 3;
};
# lnd
services.lnd.enforceTor = true;
# Create user operator which can use bitcoin-cli and lightning-cli
users.users.operator = {
isNormalUser = true;
extraGroups = [ config.services.bitcoind.group ]
++ (if config.services.clightning.enable then [ "clightning" ] else [ ])
++ (if config.services.lnd.enable then [ "lnd" ] else [ ])
++ (if config.services.liquidd.enable then [ config.services.liquidd.group ] else [ ])
++ (if (config.services.hardware-wallets.ledger || config.services.hardware-wallets.trezor)
then [ config.services.hardware-wallets.group ] else [ ]);
@ -111,17 +122,26 @@ in {
environment.interactiveShellInit = ''
alias bitcoin-cli='bitcoin-cli -datadir=${config.services.bitcoind.dataDir}'
alias lightning-cli='sudo -u clightning lightning-cli --lightning-dir=${config.services.clightning.dataDir}'
'' + (if config.services.liquidd.enable then ''
alias elements-cli='elements-cli -datadir=${config.services.liquidd.dataDir}'
alias liquidswap-cli='liquidswap-cli -c ${config.services.liquidd.dataDir}/elements.conf'
'' else "");
${optionalString (config.services.clightning.enable) ''
alias lightning-cli='sudo -u clightning lightning-cli --lightning-dir=${config.services.clightning.dataDir}'
''}
${optionalString (config.services.lnd.enable) ''
alias lncli='sudo -u lnd lncli --tlscertpath /secrets/lnd_cert --macaroonpath ${config.services.lnd.dataDir}/chain/bitcoin/mainnet/admin.macaroon'
''}
${optionalString (config.services.liquidd.enable) ''
alias elements-cli='elements-cli -datadir=${config.services.liquidd.dataDir}'
alias liquidswap-cli='liquidswap-cli -c ${config.services.liquidd.dataDir}/elements.conf'
''}
'';
# Unfortunately c-lightning doesn't allow setting the permissions of the rpc socket
# https://github.com/ElementsProject/lightning/issues/1366
security.sudo.configFile = (
if config.services.clightning.enable then ''
operator ALL=(clightning) NOPASSWD: ALL
''
else if config.services.lnd.enable then ''
operator ALL=(lnd) NOPASSWD: ALL
''
else ""
);
@ -176,6 +196,7 @@ in {
qrencode
]
++ optionals config.services.clightning.enable [clightning]
++ optionals config.services.lnd.enable [lnd]
++ optionals config.services.lightning-charge.enable [lightning-charge]
++ optionals config.services.nanopos.enable [nanopos]
++ optionals config.services.nix-bitcoin-webindex.enable [nginx]