From 19b971f21f62e5f173488204110bd787c1264263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20D=2E=20Mih=C4=83il=C4=83?= Date: Tue, 13 Aug 2019 22:57:59 +0200 Subject: [PATCH 01/11] Rename nginx certificate files --- modules/electrs.nix | 4 ++-- network/network.nix | 10 +++++----- secrets/generate_secrets.sh | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/electrs.nix b/modules/electrs.nix index 810d815..b29ae3c 100644 --- a/modules/electrs.nix +++ b/modules/electrs.nix @@ -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; diff --git a/network/network.nix b/network/network.nix index 4059e40..8195f5b 100644 --- a/network/network.nix +++ b/network/network.nix @@ -36,15 +36,15 @@ let group = "clightning"; permissions = "0440"; }; - ssl_certificate_key = { - keyFile = ../secrets/ssl_certificate_key.key; + nginx_key = { + keyFile = ../secrets/nginx.key; destDir = "/secrets/"; user = "nginx"; group = "root"; permissions = "0440"; }; - ssl_certificate = { - keyFile = ../secrets/ssl_certificate.crt; + nginx_cert = { + keyFile = ../secrets/nginx.cert; destDir = "/secrets/"; user = "nginx"; group = "root"; @@ -65,6 +65,6 @@ in { // (if (config.services.nanopos.enable) then { inherit lightning-charge-api-token-for-nanopos; } else { }) // (if (config.services.liquidd.enable) then { inherit liquid-rpcpassword; } else { }) // (if (config.services.spark-wallet.enable) then { inherit spark-wallet-login; } else { }) - // (if (config.services.electrs.enable) then { inherit ssl_certificate_key ssl_certificate; } else { }); + // (if (config.services.electrs.enable) then { inherit nginx_key nginx_cert; } else { }); } // (bitcoin-node { inherit config pkgs; }); } diff --git a/secrets/generate_secrets.sh b/secrets/generate_secrets.sh index 460de78..c983aeb 100755 --- a/secrets/generate_secrets.sh +++ b/secrets/generate_secrets.sh @@ -19,7 +19,7 @@ echo Write secrets to $SECRETSFILE echo Done echo Generate Self-Signed Cert -openssl genrsa -out secrets/ssl_certificate_key.key 2048 -openssl req -new -key secrets/ssl_certificate_key.key -out secrets/ssl_certificate.csr -subj "/C=KN" -openssl x509 -req -days 1825 -in secrets/ssl_certificate.csr -signkey secrets/ssl_certificate_key.key -out secrets/ssl_certificate.crt +openssl genrsa -out secrets/nginx.key 2048 +openssl req -new -key secrets/nginx.key -out secrets/nginx.csr -subj "/C=KN" +openssl x509 -req -days 1825 -in secrets/nginx.csr -signkey secrets/nginx.key -out secrets/nginx.cert echo Done From 4acf5cd32c3ef899fa7900c22e491b7b148b119a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20D=2E=20Mih=C4=83il=C4=83?= Date: Tue, 13 Aug 2019 23:22:41 +0200 Subject: [PATCH 02/11] Remove unused nginx.csr file --- secrets/generate_secrets.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/secrets/generate_secrets.sh b/secrets/generate_secrets.sh index c983aeb..18890da 100755 --- a/secrets/generate_secrets.sh +++ b/secrets/generate_secrets.sh @@ -22,4 +22,5 @@ echo Generate Self-Signed Cert openssl genrsa -out secrets/nginx.key 2048 openssl req -new -key secrets/nginx.key -out secrets/nginx.csr -subj "/C=KN" openssl x509 -req -days 1825 -in secrets/nginx.csr -signkey secrets/nginx.key -out secrets/nginx.cert +rm secrets/nginx.csr echo Done From 9b0753135cfb0ca16df61a48fd157d84b5543a1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20D=2E=20Mih=C4=83il=C4=83?= Date: Mon, 5 Aug 2019 10:44:38 +0200 Subject: [PATCH 03/11] Add LND support --- configuration.nix | 9 +++ modules/bitcoind.nix | 14 +++- modules/default.nix | 1 + modules/lnd.nix | 128 +++++++++++++++++++++++++++++++ modules/nix-bitcoin-pkgs.nix | 1 + modules/nix-bitcoin-services.nix | 3 - modules/nix-bitcoin.nix | 39 ++++++++-- network/network.nix | 22 ++++++ pkgs/nodeinfo/nodeinfo.sh | 21 +++-- secrets/generate_secrets.sh | 8 ++ secrets/openssl.cnf | 32 ++++++++ 11 files changed, 261 insertions(+), 17 deletions(-) create mode 100644 modules/lnd.nix create mode 100644 secrets/openssl.cnf diff --git a/configuration.nix b/configuration.nix index 5bbed3b..4cd716d 100644 --- a/configuration.nix +++ b/configuration.nix @@ -30,6 +30,15 @@ # default nix-bitcoin nodes offer outgoing connectivity. # services.clightning.autolisten = true; + ### LND + # Disable clightning and uncomment the following line in order to enable lnd, + # a lightning implementation written in Go. + # services.lnd.enable = assert (!config.services.clightning.enable); true; + # WARNING: If you use lnd, you should manually backup your wallet mnemonic + # seed. In order to do so, you can run the following command after the + # lnd service starts: + # nixops scp --from bitcoin-node /secrets/lnd-seed-mnemonic ./secrets/lnd-seed-mnemonic + ### SPARK WALLET # Enable this module to use spark-wallet, a minimalistic wallet GUI for # c-lightning, accessible over the web or through mobile and desktop apps. diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix index 04d5aee..0751b71 100644 --- a/modules/bitcoind.nix +++ b/modules/bitcoind.nix @@ -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 - ); + ) // optionals config.services.lnd.enable nix-bitcoin-services.allowAnyProtocol; # FOR ZMQ }; systemd.services.bitcoind-import-banlist = { description = "Bitcoin daemon banlist importer"; diff --git a/modules/default.nix b/modules/default.nix index c4f0079..621ab8f 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -11,4 +11,5 @@ nix-bitcoin-webindex = ./nix-bitcoin-webindex.nix; spark-wallet = ./spark-wallet.nix; recurring-donations = ./recurring-donations.nix; + lnd = ./lnd.nix; } diff --git a/modules/lnd.nix b/modules/lnd.nix new file mode 100644 index 0000000..831c680 --- /dev/null +++ b/modules/lnd.nix @@ -0,0 +1,128 @@ +{ 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} + 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 + + 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 + +${pkgs.coreutils}/bin/sleep 5 + +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 GET https://127.0.0.1:8080/v1/genseed | ${pkgs.jq}/bin/jq -c '.cipher_seed_mnemonic' > /secrets/lnd-seed-mnemonic + + ${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 + + ${pkgs.coreutils}/bin/echo wallet created +else + ${pkgs.coreutils}/bin/echo unlocking wallet + + ${pkgs.curl}/bin/curl -s \ + -H "Grpc-Metadata-macaroon: $(${pkgs.xxd}/bin/xxd -ps -u -c 1000 ${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 + + ${pkgs.coreutils}/bin/echo wallet unlocked +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 lnd.conf."; + }; + 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 + }; + }; +} diff --git a/modules/nix-bitcoin-pkgs.nix b/modules/nix-bitcoin-pkgs.nix index 918a257..b88274c 100644 --- a/modules/nix-bitcoin-pkgs.nix +++ b/modules/nix-bitcoin-pkgs.nix @@ -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 { }; }; } diff --git a/modules/nix-bitcoin-services.nix b/modules/nix-bitcoin-services.nix index fd43bde..2caee5b 100644 --- a/modules/nix-bitcoin-services.nix +++ b/modules/nix-bitcoin-services.nix @@ -42,6 +42,3 @@ in ''; }; } - - - diff --git a/modules/nix-bitcoin.nix b/modules/nix-bitcoin.nix index 530a347..43152e0 100644 --- a/modules/nix-bitcoin.nix +++ b/modules/nix-bitcoin.nix @@ -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,32 +103,51 @@ in { version = 3; }; + # lnd + services.lnd.enforceTor = true; + services.tor.hiddenServices.lnd = { + map = [{ + port = 9735; toPort = 9735; + }]; + version = 3; + }; + # 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 [ ]); }; # Give operator access to onion hostnames services.onion-chef.enable = true; - services.onion-chef.access.operator = [ "bitcoind" "clightning" "nginx" "liquidd" "spark-wallet" "electrs" "sshd" ]; + services.onion-chef.access.operator = [ "bitcoind" "clightning" "lnd" "nginx" "liquidd" "spark-wallet" "electrs" "sshd" ]; 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 +202,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] diff --git a/network/network.nix b/network/network.nix index 8195f5b..96997ca 100644 --- a/network/network.nix +++ b/network/network.nix @@ -7,6 +7,13 @@ let group = "bitcoinrpc"; permissions = "0440"; }; + lnd-wallet-password = { + text = secrets.lnd-wallet-password; + destDir = "/secrets/"; + user = "lnd"; + group = "lnd"; + permissions = "0440"; + }; lightning-charge-api-token = { text = "API_TOKEN=" + secrets.lightning-charge-api-token; destDir = "/secrets/"; @@ -50,6 +57,20 @@ let group = "root"; permissions = "0440"; }; + lnd_key = { + keyFile = ../secrets/lnd.key; + destDir = "/secrets/"; + user = "lnd"; + group = "lnd"; + permissions = "0440"; + }; + lnd_cert = { + keyFile = ../secrets/lnd.cert; + destDir = "/secrets/"; + user = "lnd"; + group = "lnd"; + permissions = "0440"; + }; in { network.description = "Bitcoin Core node"; @@ -61,6 +82,7 @@ in { deployment.keys = { inherit bitcoin-rpcpassword; } + // (if (config.services.lnd.enable) then { inherit lnd-wallet-password lnd_key lnd_cert; } else { }) // (if (config.services.lightning-charge.enable) then { inherit lightning-charge-api-token; } else { }) // (if (config.services.nanopos.enable) then { inherit lightning-charge-api-token-for-nanopos; } else { }) // (if (config.services.liquidd.enable) then { inherit liquid-rpcpassword; } else { }) diff --git a/pkgs/nodeinfo/nodeinfo.sh b/pkgs/nodeinfo/nodeinfo.sh index 62529fa..a013fd3 100644 --- a/pkgs/nodeinfo/nodeinfo.sh +++ b/pkgs/nodeinfo/nodeinfo.sh @@ -2,14 +2,21 @@ set -e set -o pipefail BITCOIND_ONION="$(cat /var/lib/onion-chef/operator/bitcoind)" -CLIGHTNING_NODEID=$(sudo -u clightning lightning-cli --lightning-dir=/var/lib/clightning getinfo | jq -r '.id') -CLIGHTNING_ONION="$(cat /var/lib/onion-chef/operator/clightning)" -CLIGHTNING_ID="$CLIGHTNING_NODEID@$CLIGHTNING_ONION:9735" - echo BITCOIND_ONION="$BITCOIND_ONION" -echo CLIGHTNING_NODEID="$CLIGHTNING_NODEID" -echo CLIGHTNING_ONION="$CLIGHTNING_ONION" -echo CLIGHTNING_ID="$CLIGHTNING_ID" + +if [ -x "$(command -v clightning)" ]; then + CLIGHTNING_NODEID=$(sudo -u clightning lightning-cli --lightning-dir=/var/lib/clightning getinfo | jq -r '.id') + CLIGHTNING_ONION="$(cat /var/lib/onion-chef/operator/clightning)" + CLIGHTNING_ID="$CLIGHTNING_NODEID@$CLIGHTNING_ONION:9735" + echo CLIGHTNING_NODEID="$CLIGHTNING_NODEID" + echo CLIGHTNING_ONION="$CLIGHTNING_ONION" + echo CLIGHTNING_ID="$CLIGHTNING_ID" +fi + +if [ -x "$(command -v lncli)" ]; then + LND_NODEID=$(sudo -u lnd lncli --tlscertpath /secrets/lnd_cert --macaroonpath /var/lib/lnd/chain/bitcoin/mainnet/admin.macaroon getinfo | jq -r '.uris[0]') + echo LND_NODEID="$LND_NODEID" +fi NGINX_ONION_FILE=/var/lib/onion-chef/operator/nginx if [ -e "$NGINX_ONION_FILE" ]; then diff --git a/secrets/generate_secrets.sh b/secrets/generate_secrets.sh index 18890da..bc56859 100755 --- a/secrets/generate_secrets.sh +++ b/secrets/generate_secrets.sh @@ -11,6 +11,7 @@ echo Write secrets to $SECRETSFILE { echo \{ echo " bitcoinrpcpassword = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" + echo " lnd-wallet-password = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" echo " lightning-charge-api-token = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" echo " liquidrpcpassword = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" echo " spark-wallet-password = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" @@ -24,3 +25,10 @@ openssl req -new -key secrets/nginx.key -out secrets/nginx.csr -subj "/C=KN" openssl x509 -req -days 1825 -in secrets/nginx.csr -signkey secrets/nginx.key -out secrets/nginx.cert rm secrets/nginx.csr echo Done + +echo Generate LND compatible TLS Cert +openssl ecparam -genkey -name prime256v1 -out secrets/lnd.key +openssl req -config secrets/openssl.cnf -new -sha256 -key secrets/lnd.key -out secrets/lnd.csr -subj '/CN=localhost/O=lnd' +openssl req -config secrets/openssl.cnf -x509 -sha256 -days 1825 -key secrets/lnd.key -in secrets/lnd.csr -out secrets/lnd.cert +rm secrets/lnd.csr +echo Done diff --git a/secrets/openssl.cnf b/secrets/openssl.cnf new file mode 100644 index 0000000..66f25e4 --- /dev/null +++ b/secrets/openssl.cnf @@ -0,0 +1,32 @@ +[ req ] +#default_bits = 2048 +#default_md = sha256 +#default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_min = 2 +countryName_max = 2 +stateOrProvinceName = State or Province Name (full name) +localityName = Locality Name (eg, city) +0.organizationName = Organization Name (eg, company) +organizationalUnitName = Organizational Unit Name (eg, section) +commonName = Common Name (eg, fully qualified host name) +commonName_max = 64 +emailAddress = Email Address +emailAddress_max = 64 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +[ v3_ca ] +subjectAltName = @alt_names + +[ alt_names ] +IP.1 = 127.0.0.1 +DNS.1 = localhost From d6f961db89ab0fdc03658a643fb6b0a6969cb9d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20D=2E=20Mih=C4=83il=C4=83?= Date: Thu, 22 Aug 2019 16:59:28 +0200 Subject: [PATCH 04/11] Reuse lnd seed --- modules/lnd.nix | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/modules/lnd.nix b/modules/lnd.nix index 831c680..686bd3f 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -28,26 +28,30 @@ let #!/bin/sh set -e +umask 377 ${pkgs.coreutils}/bin/sleep 5 -if [ ! -f ${cfg.dataDir}/chain/bitcoin/mainnet/wallet.db ] +if [ ! -f /secrets/lnd-seed-mnemonic ] then - ${pkgs.coreutils}/bin/echo creating LND wallet + ${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 - - ${pkgs.coreutils}/bin/echo wallet created else - ${pkgs.coreutils}/bin/echo unlocking wallet + ${pkgs.coreutils}/bin/echo Unlocking lnd wallet ${pkgs.curl}/bin/curl -s \ -H "Grpc-Metadata-macaroon: $(${pkgs.xxd}/bin/xxd -ps -u -c 1000 ${cfg.dataDir}/chain/bitcoin/mainnet/admin.macaroon)" \ @@ -55,8 +59,6 @@ else -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 - - ${pkgs.coreutils}/bin/echo wallet unlocked fi exit 0 From 5a2517b926516b511bb7879d2c8f1ac5d5e8d8e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20D=2E=20Mih=C4=83il=C4=83?= Date: Thu, 22 Aug 2019 19:23:53 +0200 Subject: [PATCH 05/11] Check for existing secrets and create them more granularly This allows an user to delete only the lnd certs for example and run nix-shell to recreate them, leaving other secrets intact. --- secrets/generate_secrets.sh | 61 +++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/secrets/generate_secrets.sh b/secrets/generate_secrets.sh index bc56859..3b5f15b 100755 --- a/secrets/generate_secrets.sh +++ b/secrets/generate_secrets.sh @@ -2,33 +2,40 @@ SECRETSFILE=secrets/secrets.nix -if [ -e "$SECRETSFILE" ]; then - echo $SECRETSFILE already exists. No new secrets were generated. - exit 1 +if [ ! -e "$SECRETSFILE" ]; then + echo Write secrets to $SECRETSFILE + { + echo \{ + echo " bitcoinrpcpassword = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" + echo " lnd-wallet-password = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" + echo " lightning-charge-api-token = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" + echo " liquidrpcpassword = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" + echo " spark-wallet-password = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" + echo \} + } >> $SECRETSFILE + echo Done +else + echo $SECRETSFILE already exists. Skipping. fi -echo Write secrets to $SECRETSFILE -{ - echo \{ - echo " bitcoinrpcpassword = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" - echo " lnd-wallet-password = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" - echo " lightning-charge-api-token = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" - echo " liquidrpcpassword = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" - echo " spark-wallet-password = \"$(apg -m 20 -x 20 -M Ncl -n 1)\";" - echo \} -} >> $SECRETSFILE -echo Done +if [ ! -e secrets/nginx.key ] || [ ! -e secrets/nginx.cert ]; then + echo Generate Nginx Self-Signed Cert + openssl genrsa -out secrets/nginx.key 2048 + openssl req -new -key secrets/nginx.key -out secrets/nginx.csr -subj "/C=KN" + openssl x509 -req -days 1825 -in secrets/nginx.csr -signkey secrets/nginx.key -out secrets/nginx.cert + rm secrets/nginx.csr + echo Done +else + echo Nginx Cert already exists. Skipping. +fi -echo Generate Self-Signed Cert -openssl genrsa -out secrets/nginx.key 2048 -openssl req -new -key secrets/nginx.key -out secrets/nginx.csr -subj "/C=KN" -openssl x509 -req -days 1825 -in secrets/nginx.csr -signkey secrets/nginx.key -out secrets/nginx.cert -rm secrets/nginx.csr -echo Done - -echo Generate LND compatible TLS Cert -openssl ecparam -genkey -name prime256v1 -out secrets/lnd.key -openssl req -config secrets/openssl.cnf -new -sha256 -key secrets/lnd.key -out secrets/lnd.csr -subj '/CN=localhost/O=lnd' -openssl req -config secrets/openssl.cnf -x509 -sha256 -days 1825 -key secrets/lnd.key -in secrets/lnd.csr -out secrets/lnd.cert -rm secrets/lnd.csr -echo Done +if [ ! -e secrets/lnd.key ] || [ ! -e secrets/lnd.cert ]; then + echo Generate LND compatible TLS Cert + openssl ecparam -genkey -name prime256v1 -out secrets/lnd.key + openssl req -config secrets/openssl.cnf -new -sha256 -key secrets/lnd.key -out secrets/lnd.csr -subj '/CN=localhost/O=lnd' + openssl req -config secrets/openssl.cnf -x509 -sha256 -days 1825 -key secrets/lnd.key -in secrets/lnd.csr -out secrets/lnd.cert + rm secrets/lnd.csr + echo Done +else + echo LND cert already exists. Skipping. +fi From 700fdf6febdc6e4fff3d00482a28f3d0bebb1094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20D=2E=20Mih=C4=83il=C4=83?= Date: Fri, 23 Aug 2019 01:38:27 +0200 Subject: [PATCH 06/11] Add logdir and tor.privatekeypath to lnd.conf This will put the logs dir and tor priv keys directly in the datadir of lnd. Before this commit, they were stored in a .lnd dir inside the datadir. --- modules/lnd.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/lnd.nix b/modules/lnd.nix index 686bd3f..6d1440f 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -7,6 +7,7 @@ let 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 @@ -17,6 +18,7 @@ let 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} From fccd91972aa935e9452cf63d75c40764aa1cdfaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20D=2E=20Mih=C4=83il=C4=83?= Date: Sat, 24 Aug 2019 22:05:41 +0200 Subject: [PATCH 07/11] Fix "value is a list [...]" error when lnd is not enabled --- modules/bitcoind.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix index 0751b71..13bb18a 100644 --- a/modules/bitcoind.nix +++ b/modules/bitcoind.nix @@ -251,7 +251,7 @@ in { // (if cfg.enforceTor then nix-bitcoin-services.allowTor else nix-bitcoin-services.allowAnyIP - ) // optionals config.services.lnd.enable nix-bitcoin-services.allowAnyProtocol; # FOR ZMQ + ) // optionalAttrs config.services.lnd.enable nix-bitcoin-services.allowAnyProtocol; # FOR ZMQ }; systemd.services.bitcoind-import-banlist = { description = "Bitcoin daemon banlist importer"; From 101ae3c37075bb4893652d7c04743fcc18d4ba36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20D=2E=20Mih=C4=83il=C4=83?= Date: Sun, 25 Aug 2019 01:24:26 +0200 Subject: [PATCH 08/11] Instruct user to backup channel.backup --- configuration.nix | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/configuration.nix b/configuration.nix index 4cd716d..66451b6 100644 --- a/configuration.nix +++ b/configuration.nix @@ -34,10 +34,14 @@ # Disable clightning and uncomment the following line in order to enable lnd, # a lightning implementation written in Go. # services.lnd.enable = assert (!config.services.clightning.enable); true; - # WARNING: If you use lnd, you should manually backup your wallet mnemonic - # seed. In order to do so, you can run the following command after the - # lnd service starts: + ## WARNING + # If you use lnd, you should manually backup your wallet mnemonic + # seed. This will allow you to recover on-chain funds. You can run the + # following command after the lnd service starts: # nixops scp --from bitcoin-node /secrets/lnd-seed-mnemonic ./secrets/lnd-seed-mnemonic + # You should also backup your channel state after opening new channels. + # This will allow you to recover off-chain funds, by force-closing channels. + # nixops scp --from bitcoin-node /var/lib/lnd/chain/bitcoin/mainnet/channel.backup /my-backup-path/channel.backup ### SPARK WALLET # Enable this module to use spark-wallet, a minimalistic wallet GUI for From 588002315882d2e94490efe33f49a209bc10f68d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20D=2E=20Mih=C4=83il=C4=83?= Date: Sun, 25 Aug 2019 02:01:05 +0200 Subject: [PATCH 09/11] Increase xxd column size --- modules/lnd.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lnd.nix b/modules/lnd.nix index 6d1440f..58e7848 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -56,7 +56,7 @@ else ${pkgs.coreutils}/bin/echo Unlocking lnd wallet ${pkgs.curl}/bin/curl -s \ - -H "Grpc-Metadata-macaroon: $(${pkgs.xxd}/bin/xxd -ps -u -c 1000 ${cfg.dataDir}/chain/bitcoin/mainnet/admin.macaroon)" \ + -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)\"}" \ From 1f407ef22c88518995e6c90facbea43e618952ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20D=2E=20Mih=C4=83il=C4=83?= Date: Sun, 25 Aug 2019 02:11:45 +0200 Subject: [PATCH 10/11] Remove lnd user from onion-chef --- modules/nix-bitcoin.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nix-bitcoin.nix b/modules/nix-bitcoin.nix index 43152e0..e7b12cc 100644 --- a/modules/nix-bitcoin.nix +++ b/modules/nix-bitcoin.nix @@ -124,7 +124,7 @@ in { }; # Give operator access to onion hostnames services.onion-chef.enable = true; - services.onion-chef.access.operator = [ "bitcoind" "clightning" "lnd" "nginx" "liquidd" "spark-wallet" "electrs" "sshd" ]; + services.onion-chef.access.operator = [ "bitcoind" "clightning" "nginx" "liquidd" "spark-wallet" "electrs" "sshd" ]; environment.interactiveShellInit = '' alias bitcoin-cli='bitcoin-cli -datadir=${config.services.bitcoind.dataDir}' From 9d029fd1afff4fe79bf8ea7d89bda64bd4c68dc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20D=2E=20Mih=C4=83il=C4=83?= Date: Sun, 25 Aug 2019 02:25:35 +0200 Subject: [PATCH 11/11] Remove lnd explicit tor onion service config --- modules/nix-bitcoin.nix | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/nix-bitcoin.nix b/modules/nix-bitcoin.nix index e7b12cc..85c869f 100644 --- a/modules/nix-bitcoin.nix +++ b/modules/nix-bitcoin.nix @@ -105,12 +105,6 @@ in { # lnd services.lnd.enforceTor = true; - services.tor.hiddenServices.lnd = { - map = [{ - port = 9735; toPort = 9735; - }]; - version = 3; - }; # Create user operator which can use bitcoin-cli and lightning-cli users.users.operator = {