From 0d2db4e79f20324b80e7683a21af7aea89470b06 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Wed, 8 Sep 2021 17:01:09 +0200 Subject: [PATCH 01/11] backups: add option `postgresqlDatabases` This simplifies defining postgresql backups. This change is covered by tests.py. --- modules/backups.nix | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/modules/backups.nix b/modules/backups.nix index a7747c6..2425214 100644 --- a/modules/backups.nix +++ b/modules/backups.nix @@ -18,17 +18,22 @@ let ${config.services.nbxplorer.dataDir} ${config.services.btcpayserver.dataDir} ${config.services.joinmarket.dataDir} - ${config.services.postgresqlBackup.location}/btcpaydb.sql.gz ${optionalString config.nix-bitcoin.generateSecrets "${config.nix-bitcoin.secretsDir}"} /var/lib/tor /var/lib/nixos + ${builtins.concatStringsSep "\n" postgresqlBackupPaths} + # Extra files ${cfg.extraFiles} # Exclude all unspecified files and directories - / ''; + + postgresqlBackupDir = config.services.postgresqlBackup.location; + postgresqlBackupPaths = map (db: "${postgresqlBackupDir}/${db}.sql.gz") cfg.postgresqlDatabases; + postgresqlBackupServices = map (db: "postgresqlBackup-${db}.service") cfg.postgresqlDatabases; in { options.services.backups = { enable = mkEnableOption "Backups service"; @@ -53,6 +58,11 @@ in { Run backup with the given frequency. If null, do not run automatically. ''; }; + postgresqlDatabases = mkOption { + type = types.listOf types.str; + default = []; + description = "List of database names to backup."; + }; extraFiles = mkOption { type = types.lines; default = ""; @@ -63,8 +73,7 @@ in { }; }; - config = mkIf cfg.enable (mkMerge [ - { + config = mkIf cfg.enable { environment.systemPackages = [ pkgs.duplicity ]; services.duplicity = { @@ -78,17 +87,18 @@ in { secretFile = "${config.nix-bitcoin.secretsDir}/backup-encryption-env"; }; - nix-bitcoin.secrets.backup-encryption-env.user = "root"; - } - (mkIf config.services.btcpayserver.enable { + systemd.services.duplicity = { + wants = postgresqlBackupServices; + after = postgresqlBackupServices; + }; + services.postgresqlBackup = { - enable = true; - databases = [ "btcpaydb" ]; + enable = mkIf (cfg.postgresqlDatabases != []) true; + databases = cfg.postgresqlDatabases; }; - systemd.services.duplicity = rec { - wants = [ "postgresqlBackup-btcpaydb.service" ]; - after = wants; - }; - }) - ]); + + nix-bitcoin.secrets.backup-encryption-env.user = "root"; + + services.backups.postgresqlDatabases = mkIf config.services.btcpayserver.enable [ "btcpaydb" ]; + }; } From 5087ce245f15e581e5efb9276806cb1dd9d99d55 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Wed, 8 Sep 2021 17:01:10 +0200 Subject: [PATCH 02/11] minor cleanups - btcpayserver: remove unneeded trailing semicolons - krops/get-sha256: `tail` is unneeded because `nix-prefetch-url` just outputs a single line containing the hash. --- modules/btcpayserver.nix | 4 ++-- pkgs/krops/get-sha256.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix index 1e1f45f..751614f 100644 --- a/modules/btcpayserver.nix +++ b/modules/btcpayserver.nix @@ -210,9 +210,9 @@ in { install -m 600 ${configFile} '${cfg.btcpayserver.dataDir}/settings.config' ${optionalString (cfg.btcpayserver.lightningBackend == "lnd") '' { - echo -n "${lndConfig}"; + echo -n "${lndConfig}" ${pkgs.openssl}/bin/openssl x509 -noout -fingerprint -sha256 -in ${config.nix-bitcoin.secretsDir}/lnd-cert \ - | sed -e 's/.*=//;s/://g'; + | sed -e 's/.*=//;s/://g' } >> '${cfg.btcpayserver.dataDir}/settings.config' ''} ''; diff --git a/pkgs/krops/get-sha256.sh b/pkgs/krops/get-sha256.sh index 91b4049..d7cd792 100755 --- a/pkgs/krops/get-sha256.sh +++ b/pkgs/krops/get-sha256.sh @@ -5,7 +5,7 @@ set -euo pipefail archive_hash () { repo=$1 rev=$2 - nix-prefetch-url --unpack "https://github.com/${repo}/archive/${rev}.tar.gz" 2> /dev/null | tail -n 1 + nix-prefetch-url --unpack "https://github.com/${repo}/archive/${rev}.tar.gz" 2> /dev/null } echo "Fetching latest krops commit" From 955b44404cc16fefa038f85d4c58929ba558e5be Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Wed, 8 Sep 2021 17:01:11 +0200 Subject: [PATCH 03/11] delete helper/fetch-channel This script was obsoleted by switching to flakes. --- helper/fetch-channel | 6 ------ 1 file changed, 6 deletions(-) delete mode 100755 helper/fetch-channel diff --git a/helper/fetch-channel b/helper/fetch-channel deleted file mode 100755 index bdc64d1..0000000 --- a/helper/fetch-channel +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -rev=$1 -sha256=$(nix-prefetch-url --unpack https://github.com/nixos/nixpkgs/archive/$rev.tar.gz) -echo "rev = \"$rev\";" -echo "sha256 = \"$sha256\";" From be12a49933aa0034893f4acf06c86766d62f9c87 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Wed, 8 Sep 2021 17:01:12 +0200 Subject: [PATCH 04/11] lightning-pool/loop: extract lnd variable --- modules/lightning-loop.nix | 15 +++++++++------ modules/lightning-pool.nix | 7 +++++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/modules/lightning-loop.nix b/modules/lightning-loop.nix index 18cce78..1eed2ff 100644 --- a/modules/lightning-loop.nix +++ b/modules/lightning-loop.nix @@ -6,6 +6,9 @@ let cfg = config.services.lightning-loop; nbLib = config.nix-bitcoin.lib; secretsDir = config.nix-bitcoin.secretsDir; + + lnd = config.services.lnd; + network = config.services.bitcoind.network; rpclisten = "${cfg.rpcAddress}:${toString cfg.rpcPort}"; configFile = builtins.toFile "loop.conf" '' @@ -17,8 +20,8 @@ let tlscertpath=${secretsDir}/loop-cert tlskeypath=${secretsDir}/loop-key - lnd.host=${config.services.lnd.rpcAddress}:${toString config.services.lnd.rpcPort} - lnd.macaroonpath=${config.services.lnd.networkDir}/admin.macaroon + lnd.host=${lnd.rpcAddress}:${toString lnd.rpcPort} + lnd.macaroonpath=${lnd.networkDir}/admin.macaroon lnd.tlspath=${secretsDir}/lnd-cert ${optionalString (cfg.proxy != null) "server.proxy=${cfg.proxy}"} @@ -89,7 +92,7 @@ in { environment.systemPackages = [ cfg.package (hiPrio cfg.cli) ]; systemd.tmpfiles.rules = [ - "d '${cfg.dataDir}' 0770 ${config.services.lnd.user} ${config.services.lnd.group} - -" + "d '${cfg.dataDir}' 0770 ${lnd.user} ${lnd.group} - -" ]; systemd.services.lightning-loop = { @@ -98,7 +101,7 @@ in { after = [ "lnd.service" ]; serviceConfig = nbLib.defaultHardening // { ExecStart = "${cfg.package}/bin/loopd --configfile=${configFile}"; - User = config.services.lnd.user; + User = lnd.user; Restart = "on-failure"; RestartSec = "10s"; ReadWritePaths = cfg.dataDir; @@ -106,8 +109,8 @@ in { }; nix-bitcoin.secrets = { - loop-key.user = config.services.lnd.user; - loop-cert.user = config.services.lnd.user; + loop-key.user = lnd.user; + loop-cert.user = lnd.user; }; }; } diff --git a/modules/lightning-pool.nix b/modules/lightning-pool.nix index 74ba9d5..0ec6bb6 100644 --- a/modules/lightning-pool.nix +++ b/modules/lightning-pool.nix @@ -6,6 +6,9 @@ let cfg = config.services.lightning-pool; nbLib = config.nix-bitcoin.lib; secretsDir = config.nix-bitcoin.secretsDir; + + lnd = config.services.lnd; + network = config.services.bitcoind.network; rpclisten = "${cfg.rpcAddress}:${toString cfg.rpcPort}"; configFile = builtins.toFile "pool.conf" '' @@ -13,8 +16,8 @@ let restlisten=${cfg.restAddress}:${toString cfg.restPort} ${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"} - lnd.host=${config.services.lnd.rpcAddress}:${toString config.services.lnd.rpcPort} - lnd.macaroondir=${config.services.lnd.networkDir} + lnd.host=${lnd.rpcAddress}:${toString lnd.rpcPort} + lnd.macaroondir=${lnd.networkDir} lnd.tlspath=${secretsDir}/lnd-cert ${cfg.extraConfig} From 2c8e29b35bc5b8165c854966594a68456e341f62 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Wed, 8 Sep 2021 17:01:13 +0200 Subject: [PATCH 05/11] lnd: extract option `certPath` Improves service encapsulation. --- modules/btcpayserver.nix | 2 +- modules/charge-lnd.nix | 2 +- modules/lightning-loop.nix | 2 +- modules/lightning-pool.nix | 3 +-- modules/lnd-rest-onion-service.nix | 3 +-- modules/lnd.nix | 11 ++++++++--- 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix index 751614f..0e5d9e6 100644 --- a/modules/btcpayserver.nix +++ b/modules/btcpayserver.nix @@ -211,7 +211,7 @@ in { ${optionalString (cfg.btcpayserver.lightningBackend == "lnd") '' { echo -n "${lndConfig}" - ${pkgs.openssl}/bin/openssl x509 -noout -fingerprint -sha256 -in ${config.nix-bitcoin.secretsDir}/lnd-cert \ + ${pkgs.openssl}/bin/openssl x509 -noout -fingerprint -sha256 -in ${config.services.lnd.certPath} \ | sed -e 's/.*=//;s/://g' } >> '${cfg.btcpayserver.dataDir}/settings.config' ''} diff --git a/modules/charge-lnd.nix b/modules/charge-lnd.nix index b6cf8aa..c3d4580 100644 --- a/modules/charge-lnd.nix +++ b/modules/charge-lnd.nix @@ -105,7 +105,7 @@ in macaroonDir=${dataDir}/lnddir-proxy/data/chain/bitcoin/mainnet mkdir -p $macaroonDir ln -sf /run/lnd/charge-lnd.macaroon $macaroonDir - ln -sf ${config.nix-bitcoin.secretsDir}/lnd-cert ${dataDir}/lnddir-proxy/tls.cert + ln -sf ${lnd.certPath} ${dataDir}/lnddir-proxy/tls.cert ''; serviceConfig = nbLib.defaultHardening // { ExecStart = '' diff --git a/modules/lightning-loop.nix b/modules/lightning-loop.nix index 1eed2ff..d6e6a65 100644 --- a/modules/lightning-loop.nix +++ b/modules/lightning-loop.nix @@ -22,7 +22,7 @@ let lnd.host=${lnd.rpcAddress}:${toString lnd.rpcPort} lnd.macaroonpath=${lnd.networkDir}/admin.macaroon - lnd.tlspath=${secretsDir}/lnd-cert + lnd.tlspath=${lnd.certPath} ${optionalString (cfg.proxy != null) "server.proxy=${cfg.proxy}"} diff --git a/modules/lightning-pool.nix b/modules/lightning-pool.nix index 0ec6bb6..7f49f3d 100644 --- a/modules/lightning-pool.nix +++ b/modules/lightning-pool.nix @@ -5,7 +5,6 @@ with lib; let cfg = config.services.lightning-pool; nbLib = config.nix-bitcoin.lib; - secretsDir = config.nix-bitcoin.secretsDir; lnd = config.services.lnd; @@ -18,7 +17,7 @@ let lnd.host=${lnd.rpcAddress}:${toString lnd.rpcPort} lnd.macaroondir=${lnd.networkDir} - lnd.tlspath=${secretsDir}/lnd-cert + lnd.tlspath=${lnd.certPath} ${cfg.extraConfig} ''; diff --git a/modules/lnd-rest-onion-service.nix b/modules/lnd-rest-onion-service.nix index 1d873cc..344885e 100644 --- a/modules/lnd-rest-onion-service.nix +++ b/modules/lnd-rest-onion-service.nix @@ -5,7 +5,6 @@ with lib; let cfg = config.services.lnd.restOnionService; nbLib = config.nix-bitcoin.lib; - secretsDir = config.nix-bitcoin.secretsDir; runAsUser = config.nix-bitcoin.runAsUserCmd; lnd = config.services.lnd; @@ -17,7 +16,7 @@ let --host=$(cat ${config.nix-bitcoin.onionAddresses.dataDir}/lnd/lnd-rest) \ --port=${toString lnd.restPort} \ --lnddir=${lnd.dataDir} \ - --tlscertpath=${secretsDir}/lnd-cert "$@" + --tlscertpath=${lnd.certPath} "$@" ''; in { options.services.lnd.restOnionService = { diff --git a/modules/lnd.nix b/modules/lnd.nix index fcadc5c..7dec2d2 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -14,7 +14,7 @@ let configFile = pkgs.writeText "lnd.conf" '' datadir=${cfg.dataDir} logdir=${cfg.dataDir}/logs - tlscertpath=${secretsDir}/lnd-cert + tlscertpath=${cfg.certPath} tlskeypath=${secretsDir}/lnd-key listen=${toString cfg.address}:${toString cfg.port} @@ -126,7 +126,7 @@ in { '' ${runAsUser} ${cfg.user} ${cfg.package}/bin/lncli \ --rpcserver ${cfg.rpcAddress}:${toString cfg.rpcPort} \ - --tlscertpath '${secretsDir}/lnd-cert' \ + --tlscertpath '${cfg.certPath}' \ --macaroonpath '${networkDir}/admin.macaroon' "$@" ''; description = "Binary to connect with the lnd instance."; @@ -149,6 +149,11 @@ in { default = cfg.user; description = "The group as which to run LND."; }; + certPath = mkOption { + readOnly = true; + default = "${secretsDir}/lnd-cert"; + description = "LND TLS certificate path."; + }; inherit (nbLib) enforceTor; }; @@ -211,7 +216,7 @@ in { # Retrying is necessary because it can happen that the lnd socket is # existing, but the RPC service isn't yet, which results in error # "waiting to start, RPC services not available". - curl = "${pkgs.curl}/bin/curl -s --show-error --retry 10 --cacert ${secretsDir}/lnd-cert"; + curl = "${pkgs.curl}/bin/curl -s --show-error --retry 10 --cacert ${cfg.certPath}"; restUrl = "https://${cfg.restAddress}:${toString cfg.restPort}/v1"; in [ (nbLib.script "lnd-create-wallet" '' From e1e3d8a92bf5710098adf0314f4a89005c5d7274 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Wed, 8 Sep 2021 17:01:14 +0200 Subject: [PATCH 06/11] secrets: simplify cert generation - Remove openssl.cnf which includes many unused settings. - Generate the key and cert files with a single call to openssl. - Option `-nodes` ("no DES") disables encryption of the key file. - Option `-addext` is used to specify `subjectAltName` settings that were previously defined by openssl.cnf. The key type is unchanged. Certificate changes: - Certificate duration is now 10 years - Organization (subj 'O') is now 'loop' instead of 'loopd' for lightning-loop to simplify the code. For reference, the org. name in auto-generated loop certs is "loop autogenerated cert". - The certificate now includes all default x509v3 extensions. These were previously restricted to just `subjectAltName` by openssl.cnf. We now use the openssl defaults for simplicity. --- pkgs/generate-secrets/generate-secrets.sh | 23 +++++++-------- pkgs/generate-secrets/openssl.cnf | 36 ----------------------- 2 files changed, 11 insertions(+), 48 deletions(-) delete mode 100644 pkgs/generate-secrets/openssl.cnf diff --git a/pkgs/generate-secrets/generate-secrets.sh b/pkgs/generate-secrets/generate-secrets.sh index 56d0f4a..6def36b 100755 --- a/pkgs/generate-secrets/generate-secrets.sh +++ b/pkgs/generate-secrets/generate-secrets.sh @@ -30,16 +30,15 @@ makePasswordSecret jm-wallet-password [[ -e spark-wallet-login ]] || echo "login=spark-wallet:$(cat spark-wallet-password)" > spark-wallet-login [[ -e backup-encryption-env ]] || echo "PASSPHRASE=$(cat backup-encryption-password)" > backup-encryption-env -if [[ ! -e lnd-key || ! -e lnd-cert ]]; then - openssl ecparam -genkey -name prime256v1 -out lnd-key - openssl req -config $opensslConf -new -sha256 -key lnd-key -out lnd.csr -subj '/CN=localhost/O=lnd' - openssl req -config $opensslConf -x509 -sha256 -days 1825 -key lnd-key -in lnd.csr -out lnd-cert - rm lnd.csr -fi +makeCert() { + if [[ ! -e $name-key || ! -e $name-cert ]]; then + openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \ + -sha256 -days 3650 -nodes -keyout "$name-key" -out "$name-cert" \ + -subj "/CN=localhost/O=$name" \ + -addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:169.254.1.14,IP:169.254.1.22" + # TODO: Remove hardcoded lnd, loopd netns ips + fi +} -if [[ ! -e loop-key || ! -e loop-cert ]]; then - openssl ecparam -genkey -name prime256v1 -out loop-key - openssl req -config $opensslConf -new -sha256 -key loop-key -out loop.csr -subj '/CN=localhost/O=loopd' - openssl req -config $opensslConf -x509 -sha256 -days 1825 -key loop-key -in loop.csr -out loop-cert - rm loop.csr -fi +makeCert lnd +makeCert loop diff --git a/pkgs/generate-secrets/openssl.cnf b/pkgs/generate-secrets/openssl.cnf deleted file mode 100644 index efc6cb5..0000000 --- a/pkgs/generate-secrets/openssl.cnf +++ /dev/null @@ -1,36 +0,0 @@ -[ 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 -# TODO: Remove hardcoded lnd IP -IP.2 = 169.254.1.14 -# TODO: Remove hardcoded loopd IP -IP.3 = 169.254.1.22 From 82a2b148d8c502d56254b7c6e91731a5cbe41778 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Wed, 8 Sep 2021 17:01:15 +0200 Subject: [PATCH 07/11] secrets: minor fixes - Improve comment. - `secretsSetupMethod` is not internal because it can be set to "manual" by the user. --- modules/secrets/secrets.nix | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/secrets/secrets.nix b/modules/secrets/secrets.nix index 6c7e0a9..7618949 100644 --- a/modules/secrets/secrets.nix +++ b/modules/secrets/secrets.nix @@ -24,8 +24,8 @@ in type = types.bool; default = false; description = '' - Automatically generate all required secrets. - Make sure to create a backup of the generated secrets. + Automatically generate all required secrets at system startup. + Note: Make sure to create a backup of the generated secrets. ''; }; @@ -60,7 +60,6 @@ in }; secretsSetupMethod = mkOption { - internal = true; type = types.str; default = throw '' Error: No secrets setup method has been defined. From 8a757e0486710f2542e0e3377083d3c595c41436 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Wed, 8 Sep 2021 17:01:16 +0200 Subject: [PATCH 08/11] push-release.sh: improve --dry-run mode - Don't require OAUTH_TOKEN - Skip interactive query --- helper/push-release.sh | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/helper/push-release.sh b/helper/push-release.sh index 9058214..4a3ec46 100755 --- a/helper/push-release.sh +++ b/helper/push-release.sh @@ -3,14 +3,10 @@ set -euo pipefail REPO=fort-nix/nix-bitcoin BRANCH=master -OAUTH_TOKEN=$(pass show nix-bitcoin/github/oauth-token) +OAUTH_TOKEN= DRY_RUN= TAG_NAME= -if [[ ! $OAUTH_TOKEN ]]; then - echo "Please set OAUTH_TOKEN variable" -fi - for arg in "$@"; do case $arg in --dry-run|-n) @@ -26,18 +22,28 @@ if [[ ! $TAG_NAME ]]; then echo "$0 [--dry-run|-n] " exit fi -if [[ $DRY_RUN ]]; then echo "Dry run"; fi +if [[ $DRY_RUN ]]; then + echo "Dry run" +else + OAUTH_TOKEN=$(pass show nix-bitcoin/github/oauth-token) + if [[ ! $OAUTH_TOKEN ]]; then + echo "Please set OAUTH_TOKEN variable" + fi +fi RESPONSE=$(curl https://api.github.com/repos/$REPO/releases/latest 2> /dev/null) echo "Latest release" $(echo $RESPONSE | jq -r '.tag_name' | tail -c +2) -while true; do - read -p "Create release $TAG_NAME? [yn] " yn - case $yn in - [Yy]* ) break;; - [Nn]* ) exit;; - * ) echo "Please answer y or n.";; - esac -done + +if [[ ! $DRY_RUN ]]; then + while true; do + read -p "Create release $TAG_NAME? [yn] " yn + case $yn in + [Yy]* ) break;; + [Nn]* ) exit;; + * ) echo "Please answer y or n.";; + esac + done +fi TMPDIR=$(mktemp -d) if [[ ! $DRY_RUN ]]; then trap "rm -rf $TMPDIR" EXIT; fi From 24fd1e9bdceef5c2c21228f2f5a65bb9a2181574 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Wed, 8 Sep 2021 17:01:17 +0200 Subject: [PATCH 09/11] improve examples/shell.nix The user's local node configuration directory usually contains a copy of examples/shell.nix. 1. Move the shell implementation from shell.nix to nix-bitcoin/helper/makeShell.nix Because the shell is no longer defined locally in the user's config directory, we can now ship new shell features via nix-bitcoin updates. 2. Simplify examples/nix-bitcoin-release.nix nix-bitcoin-release.nix, as generated via `fetch-release`, now contains a simple fetchTarball statement which can be directly imported. This allows us to get rid of the extra `nix-bitcoin-unpacked` derivation which adds a dependency on the user's local nixpkgs. To keep `fetch-release` as simple as possible for easy auditing, we just fetch and verify a `nar-hash.txt` file that is now uploaded via `push-release.sh`. A migration guide for updating the user's local `shell.nix` is automatically printed when the user starts a new shell after updating nix-bitcoin. This is achieved by throwing an error in `generate-secrets`, which is called on shell startup. This commit is required to deploy the new extensible `generate-secrets` mechanism introduced in the next commit. --- examples/shell.nix | 57 +++------------------------- flake.nix | 2 +- helper/fetch-release | 24 ++++++------ helper/makeShell.nix | 43 +++++++++++++++++++++ helper/push-release.sh | 8 ++++ pkgs/default.nix | 2 +- pkgs/generate-secrets-deprecated.nix | 14 +++++++ 7 files changed, 86 insertions(+), 64 deletions(-) create mode 100644 helper/makeShell.nix create mode 100644 pkgs/generate-secrets-deprecated.nix diff --git a/examples/shell.nix b/examples/shell.nix index 47b1e47..d378e67 100644 --- a/examples/shell.nix +++ b/examples/shell.nix @@ -1,53 +1,8 @@ let - # This is either a path to a local nix-bitcoin source or an attribute set to - # be used as the fetchurl argument. - nix-bitcoin-release = import ./nix-bitcoin-release.nix; - - nix-bitcoin-path = - if builtins.isAttrs nix-bitcoin-release then nix-bitcoin-unpacked - else nix-bitcoin-release; - - nixpkgs-path = (import "${toString nix-bitcoin-path}/pkgs/nixpkgs-pinned.nix").nixpkgs; - pkgs = import nixpkgs-path {}; - nix-bitcoin = pkgs.callPackage nix-bitcoin-path {}; - - nix-bitcoin-unpacked = (import {}).runCommand "nix-bitcoin-src" {} '' - mkdir $out; tar xf ${builtins.fetchurl nix-bitcoin-release} -C $out - ''; + nix-bitcoin = toString (import ./nix-bitcoin-release.nix); in -with pkgs; -stdenv.mkDerivation rec { - name = "nix-bitcoin-environment"; - - path = lib.makeBinPath [ nix-bitcoin.extra-container ]; - - shellHook = '' - export NIX_PATH="nixpkgs=${nixpkgs-path}:nix-bitcoin=${toString nix-bitcoin-path}:." - export PATH="${path}''${PATH:+:}$PATH" - - export NIX_BITCOIN_EXAMPLES_DIR="${toString ./.}" - - fetch-release() { - ${toString nix-bitcoin-path}/helper/fetch-release - } - - krops-deploy() { - # Ensure strict permissions on secrets/ directory before rsyncing it to - # the target machine - chmod 700 ${toString ./secrets} - $(nix-build --no-out-link ${toString ./krops/deploy.nix}) - } - - # Print logo if - # 1. stdout is a TTY, i.e. we're not piping the output - # 2. the shell is interactive - if [[ -t 1 && $- == *i* ]]; then - ${figlet}/bin/figlet "nix-bitcoin" - fi - - (mkdir -p secrets; cd secrets; env -i ${nix-bitcoin.generate-secrets}) - - # Don't run this hook when another nix-shell is run inside this shell - unset shellHook - ''; -} + import "${nix-bitcoin}/helper/makeShell.nix" { + configDir = ./.; + # Set this to modify your shell + # extraShellInitCmds = (pkgs: ''''); + } diff --git a/flake.nix b/flake.nix index 12828a1..302b612 100644 --- a/flake.nix +++ b/flake.nix @@ -62,7 +62,7 @@ nbPkgs = self.mkNbPkgs { inherit system pkgs; }; packages = flake-utils.lib.flattenTree (removeAttrs nbPkgs [ - "pinned" "modulesPkgs" "nixops19_09" "krops" + "pinned" "modulesPkgs" "nixops19_09" "krops" "generate-secrets" ]) // { runVM = mkVMScript packages.vm; diff --git a/helper/fetch-release b/helper/fetch-release index 13513d8..2fe87ee 100755 --- a/helper/fetch-release +++ b/helper/fetch-release @@ -15,26 +15,28 @@ trap "rm -rf $TMPDIR" EXIT GPG_HOME=$TMPDIR/gpg-home mkdir -p -m 700 "$GPG_HOME" -cd $TMPDIR -baseUrl=https://github.com/$repo/releases/download/v$version -curl --silent -L -O $baseUrl/SHA256SUMS.txt -curl --silent -L -O $baseUrl/SHA256SUMS.txt.asc - # Import key gpg --homedir $GPG_HOME --import "$scriptDir/key-jonasnick.bin" &> /dev/null # Verify key fingerprint gpg --homedir $GPG_HOME --list-keys 36C71A37C9D988BDE82508D9B1A70E4F8DCD0366 > /dev/null -# Verify signature for SHA256SUMS.txt -gpg --homedir $GPG_HOME --verify SHA256SUMS.txt.asc &> /dev/null || { +# Fetch nar-hash of release +cd $TMPDIR +baseUrl=https://github.com/$repo/releases/download/v$version +curl --silent -L -O $baseUrl/nar-hash.txt +curl --silent -L -O $baseUrl/nar-hash.txt.asc + +# Verify signature for nar-hash +gpg --homedir $GPG_HOME --verify nar-hash.txt.asc &> /dev/null || { echo "Error: Signature verification failed. Please open an issue in the project repository." exit 1 } -sha256=$(cat SHA256SUMS.txt | cut -d\ -f1) +>&2 echo "Fetched and verified release $version" + cat < $SHA256SUMS) gpg -o $SHA256SUMS.asc -a --detach-sig $SHA256SUMS +cd $TMPDIR +nix hash to-sri --type sha256 $(nix-prefetch-url --unpack file://$ARCHIVE 2> /dev/null) > nar-hash.txt +gpg -o nar-hash.txt.asc -a --detach-sig nar-hash.txt + if [[ $DRY_RUN ]]; then echo "Created v$TAG_NAME in $TMPDIR" exit 0 @@ -77,6 +81,10 @@ post_asset() { curl -H "Authorization: token $OAUTH_TOKEN" --data-binary "@$1" -H "Content-Type: application/octet-stream" \ $GH_ASSET/$(basename $1) &> /dev/null } +post_asset nar-hash.txt +post_asset nar-hash.txt.asc +# Post additional assets for backwards compatibility. +# This allows older nix-bitcoin installations to upgrade via `fetch-release`. post_asset $ARCHIVE post_asset $SHA256SUMS post_asset $SHA256SUMS.asc diff --git a/pkgs/default.nix b/pkgs/default.nix index 1e41b01..39df452 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -9,7 +9,7 @@ let self = { spark-wallet = pkgs.callPackage ./spark-wallet { }; liquid-swap = pkgs.python3Packages.callPackage ./liquid-swap { }; joinmarket = pkgs.callPackage ./joinmarket { inherit (self) nbPython3Packages; }; - generate-secrets = pkgs.callPackage ./generate-secrets { }; + generate-secrets = import ./generate-secrets-deprecated.nix; nixops19_09 = pkgs.callPackage ./nixops { }; krops = import ./krops { }; netns-exec = pkgs.callPackage ./netns-exec { }; diff --git a/pkgs/generate-secrets-deprecated.nix b/pkgs/generate-secrets-deprecated.nix new file mode 100644 index 0000000..4bb491b --- /dev/null +++ b/pkgs/generate-secrets-deprecated.nix @@ -0,0 +1,14 @@ +throw '' + Please update the `shell.nix` of your node configuration. + + To update, do the following: + 1. Switch to the directory containing your `configuration.nix` and `shell.nix`. + 2. Run the following Bash expression (Warning: This overwrites your `shell.nix`): + + # Only update nix-bitcoin-release.nix if it contains a release hash + if grep -q sha256 nix-bitcoin-release.nix; then + ${toString ../helper/fetch-release} > nix-bitcoin-release.nix && cp ${toString ../examples/shell.nix} . + else + cp ${toString ../examples/shell.nix} . + fi +'' From a2466b11273cadc4fb4a8b5c49937e4b5f2ade3c Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Wed, 8 Sep 2021 17:01:18 +0200 Subject: [PATCH 10/11] secrets: allow extending generate-secrets `generate-secrets` is no longer a monolithic script. Instead, it's composed of the values of option `nix-bitcoin.generateSecretsCmds`. This has the following advantages: - generate-secrets is now extensible by users - Only secrets of enabled services are generated - RPC IPs in the `lnd` and `loop` certs are no longer hardcoded. Secrets are no longer automatically generated when entering nix-shell. Instead, they are generated before deployment (via `krops-deploy`) because secrets generation is now dependant on the node configuration. --- helper/makeShell.nix | 14 +++- modules/backups.nix | 6 ++ modules/bitcoind.nix | 21 +++-- modules/btcpayserver.nix | 3 + modules/joinmarket-ob-watcher.nix | 3 + modules/joinmarket.nix | 3 + modules/lightning-loop.nix | 3 + modules/liquid.nix | 3 + modules/lnd.nix | 9 ++- modules/secrets/secrets.nix | 81 +++++++++++++++++-- modules/spark-wallet.nix | 7 ++ pkgs/generate-secrets/default.nix | 15 ---- pkgs/generate-secrets/generate-secrets.sh | 44 ---------- pkgs/generate-secrets/update-and-generate.nix | 10 --- pkgs/generate-secrets/update-secrets.sh | 45 ----------- 15 files changed, 136 insertions(+), 131 deletions(-) delete mode 100644 pkgs/generate-secrets/default.nix delete mode 100755 pkgs/generate-secrets/generate-secrets.sh delete mode 100644 pkgs/generate-secrets/update-and-generate.nix delete mode 100644 pkgs/generate-secrets/update-secrets.sh diff --git a/helper/makeShell.nix b/helper/makeShell.nix index efe3c81..0fbd24b 100644 --- a/helper/makeShell.nix +++ b/helper/makeShell.nix @@ -21,12 +21,22 @@ stdenv.mkDerivation rec { ${toString ./fetch-release} } - krops-deploy() { + generate-secrets() {( + set -euo pipefail + genSecrets=$(nix-build --no-out-link -I nixos-config="${cfgDir}/configuration.nix" \ + '' -A config.nix-bitcoin.generateSecretsScript) + mkdir -p "${cfgDir}/secrets" + (cd "${cfgDir}/secrets"; $genSecrets) + )} + + krops-deploy() {( + set -euo pipefail + generate-secrets # Ensure strict permissions on secrets/ directory before rsyncing it to # the target machine chmod 700 "${cfgDir}/secrets" $(nix-build --no-out-link "${cfgDir}/krops/deploy.nix") - } + )} # Print logo if # 1. stdout is a TTY, i.e. we're not piping the output diff --git a/modules/backups.nix b/modules/backups.nix index 2425214..7a95eb3 100644 --- a/modules/backups.nix +++ b/modules/backups.nix @@ -98,6 +98,12 @@ in { }; nix-bitcoin.secrets.backup-encryption-env.user = "root"; + nix-bitcoin.generateSecretsCmds.backups = '' + makePasswordSecret backup-encryption-password + if [[ backup-encryption-password -nt backup-encryption-env ]]; then + echo "PASSPHRASE=$(cat backup-encryption-password)" > backup-encryption-env + fi + ''; services.backups.postgresqlDatabases = mkIf config.services.btcpayserver.enable [ "btcpaydb" ]; }; diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix index e2365ab..117f4d9 100644 --- a/modules/bitcoind.nix +++ b/modules/bitcoind.nix @@ -394,15 +394,22 @@ in { }; users.groups.${cfg.group} = {}; users.groups.bitcoinrpc-public = {}; + nix-bitcoin.operator.groups = [ cfg.group ]; - nix-bitcoin.secrets.bitcoin-rpcpassword-privileged.user = cfg.user; - nix-bitcoin.secrets.bitcoin-rpcpassword-public = { - user = cfg.user; - group = "bitcoinrpc-public"; - }; + nix-bitcoin.secrets = { + bitcoin-rpcpassword-privileged.user = cfg.user; + bitcoin-rpcpassword-public = { + user = cfg.user; + group = "bitcoinrpc-public"; + }; - nix-bitcoin.secrets.bitcoin-HMAC-privileged.user = cfg.user; - nix-bitcoin.secrets.bitcoin-HMAC-public.user = cfg.user; + bitcoin-HMAC-privileged.user = cfg.user; + bitcoin-HMAC-public.user = cfg.user; + }; + nix-bitcoin.generateSecretsCmds.bitcoind = '' + makeBitcoinRPCPassword privileged + makeBitcoinRPCPassword public + ''; }; } diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix index 0e5d9e6..f38b6ee 100644 --- a/modules/btcpayserver.nix +++ b/modules/btcpayserver.nix @@ -253,5 +253,8 @@ in { }; bitcoin-HMAC-btcpayserver.user = cfg.bitcoind.user; }; + nix-bitcoin.generateSecretsCmds.btcpayserver = '' + makeBitcoinRPCPassword btcpayserver + ''; }; } diff --git a/modules/joinmarket-ob-watcher.nix b/modules/joinmarket-ob-watcher.nix index 237ddb9..4b9714b 100644 --- a/modules/joinmarket-ob-watcher.nix +++ b/modules/joinmarket-ob-watcher.nix @@ -131,5 +131,8 @@ in { bitcoin-rpcpassword-joinmarket-ob-watcher.user = cfg.user; bitcoin-HMAC-joinmarket-ob-watcher.user = bitcoind.user; }; + nix-bitcoin.generateSecretsCmds.joinmarket-ob-watcher = '' + makeBitcoinRPCPassword joinmarket-ob-watcher + ''; }; } diff --git a/modules/joinmarket.nix b/modules/joinmarket.nix index 59fd2d0..a5aacc6 100644 --- a/modules/joinmarket.nix +++ b/modules/joinmarket.nix @@ -305,6 +305,9 @@ in { }; nix-bitcoin.secrets.jm-wallet-password.user = cfg.user; + nix-bitcoin.generateSecretsCmds.joinmarket = '' + makePasswordSecret jm-wallet-password + ''; } (mkIf cfg.yieldgenerator.enable { diff --git a/modules/lightning-loop.nix b/modules/lightning-loop.nix index d6e6a65..530b138 100644 --- a/modules/lightning-loop.nix +++ b/modules/lightning-loop.nix @@ -112,5 +112,8 @@ in { loop-key.user = lnd.user; loop-cert.user = lnd.user; }; + nix-bitcoin.generateSecretsCmds.lightning-loop = '' + makeCert loop '${optionalString (cfg.rpcAddress != "localhost") "IP:${cfg.rpcAddress}"}' + ''; }; } diff --git a/modules/liquid.nix b/modules/liquid.nix index 7804ba0..6fe7d14 100644 --- a/modules/liquid.nix +++ b/modules/liquid.nix @@ -247,5 +247,8 @@ in { nix-bitcoin.operator.groups = [ cfg.group ]; nix-bitcoin.secrets.liquid-rpcpassword.user = cfg.user; + nix-bitcoin.generateSecretsCmds.liquid = '' + makePasswordSecret liquid-rpcpassword + ''; }; } diff --git a/modules/lnd.nix b/modules/lnd.nix index 7dec2d2..5c7b5ec 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -293,7 +293,14 @@ in { lnd-wallet-password.user = cfg.user; lnd-key.user = cfg.user; lnd-cert.user = cfg.user; - lnd-cert.permissions = "0444"; # world readable + lnd-cert.permissions = "444"; # world readable }; + # Advantages of manually pre-generating certs: + # - Reduces dynamic state + # - Enables deployment of a mesh of server plus client nodes with predefined certs + nix-bitcoin.generateSecretsCmds.lnd = '' + makePasswordSecret lnd-wallet-password + makeCert lnd '${optionalString (cfg.rpcAddress != "localhost") "IP:${cfg.rpcAddress}"}' + ''; }; } diff --git a/modules/secrets/secrets.nix b/modules/secrets/secrets.nix index 7618949..c44ee29 100644 --- a/modules/secrets/secrets.nix +++ b/modules/secrets/secrets.nix @@ -2,9 +2,6 @@ with lib; let - cfg = config.nix-bitcoin; -in -{ options.nix-bitcoin = { secretsDir = mkOption { type = types.path; @@ -29,6 +26,14 @@ in ''; }; + generateSecretsCmds = mkOption { + type = types.attrsOf types.str; + default = {}; + description = '' + Bash expressions for generating secrets. + ''; + }; + # Currently, this is used only by ../deployment/nixops.nix deployment.secretsDir = mkOption { type = types.path; @@ -72,8 +77,68 @@ in - Set `nix-bitcoin.secretsSetupMethod = "manual"` if you want to manually setup secrets ''; }; + + generateSecretsScript = mkOption { + internal = true; + default = let + rpcauthSrc = builtins.fetchurl { + url = "https://raw.githubusercontent.com/bitcoin/bitcoin/d6cde007db9d3e6ee93bd98a9bbfdce9bfa9b15b/share/rpcauth/rpcauth.py"; + sha256 = "189mpplam6yzizssrgiyv70c9899ggh8cac76j4n7v0xqzfip07n"; + }; + rpcauth = pkgs.writers.writeBash "rpcauth" '' + exec ${pkgs.python3}/bin/python ${rpcauthSrc} "$@" + ''; + in pkgs.writers.writeBash "generate-secrets" '' + set -euo pipefail + + export PATH=${lib.makeBinPath (with pkgs; [ coreutils gnugrep ])} + + makePasswordSecret() { + # Passwords have alphabet {a-z, A-Z, 0-9} and ~119 bits of entropy + [[ -e $1 ]] || ${pkgs.pwgen}/bin/pwgen -s 20 1 > "$1" + } + makeBitcoinRPCPassword() { + user=$1 + file=bitcoin-rpcpassword-$user + HMACfile=bitcoin-HMAC-$user + makePasswordSecret "$file" + if [[ $file -nt $HMACfile ]]; then + ${rpcauth} $user $(cat "$file") | grep rpcauth | cut -d ':' -f 2 > "$HMACfile" + fi + } + makeCert() { + name=$1 + # Add leading comma if not empty + extraAltNames=''${2:+,}''${2:-} + if [[ ! -e $name-key ]]; then + # Create new key and cert + doMakeCert "-newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -keyout $name-key" + elif [[ ! -e $name-cert \ + || $(cat "$name-cert-alt-names" 2>/dev/null) != $extraAltNames ]]; then + # Create cert from existing key + doMakeCert "-key $name-key" + fi; + } + doMakeCert() { + # This fn uses global variables `name` and `extraAltNames` + keyOpts=$1 + ${pkgs.openssl}/bin/openssl req -x509 \ + -sha256 -days 3650 $keyOpts -out "$name-cert" \ + -subj "/CN=localhost/O=$name" \ + -addext "subjectAltName=DNS:localhost,IP:127.0.0.1$extraAltNames" + echo "$extraAltNames" > "$name-cert-alt-names" + } + + umask u=rw,go= + ${builtins.concatStringsSep "\n" (builtins.attrValues cfg.generateSecretsCmds)} + ''; + }; }; + cfg = config.nix-bitcoin; +in { + inherit options; + config = { # This target is active when secrets have been setup successfully. systemd.targets.nix-bitcoin-secrets = mkIf (cfg.secretsSetupMethod != "manual") { @@ -106,7 +171,7 @@ in cd "${cfg.secretsDir}" chown root: . chmod 0700 . - ${cfg.pkgs.generate-secrets} + ${cfg.generateSecretsScript} ''} setupSecret() { @@ -140,9 +205,11 @@ in # Make all other files accessible to root only unprocessedFiles=$(comm -23 <(printf '%s\n' *) <(printf '%s\n' "''${processedFiles[@]}" | sort)) - IFS=$'\n' - chown root: $unprocessedFiles - chmod 0440 $unprocessedFiles + if [[ $unprocessedFiles ]]; then + IFS=$'\n' + chown root: $unprocessedFiles + chmod 0440 $unprocessedFiles + fi # Now make the secrets dir accessible to other users chmod 0751 "$dir" diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix index ca307ce..bdefea8 100644 --- a/modules/spark-wallet.nix +++ b/modules/spark-wallet.nix @@ -83,6 +83,13 @@ in { } // nbLib.allowedIPAddresses cfg.enforceTor // nbLib.nodejs; }; + nix-bitcoin.secrets.spark-wallet-login.user = cfg.user; + nix-bitcoin.generateSecretsCmds.spark-wallet = '' + makePasswordSecret spark-wallet-password + if [[ spark-wallet-password -nt spark-wallet-login ]]; then + echo "login=spark-wallet:$(cat spark-wallet-password)" > spark-wallet-login + fi + ''; }; } diff --git a/pkgs/generate-secrets/default.nix b/pkgs/generate-secrets/default.nix deleted file mode 100644 index d04f06a..0000000 --- a/pkgs/generate-secrets/default.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ pkgs }: with pkgs; - -let - rpcauthSrc = builtins.fetchurl { - url = "https://raw.githubusercontent.com/bitcoin/bitcoin/d6cde007db9d3e6ee93bd98a9bbfdce9bfa9b15b/share/rpcauth/rpcauth.py"; - sha256 = "189mpplam6yzizssrgiyv70c9899ggh8cac76j4n7v0xqzfip07n"; - }; - rpcauth = pkgs.writeScriptBin "rpcauth" '' - exec ${pkgs.python3}/bin/python ${rpcauthSrc} "$@" - ''; -in -writers.writeBash "generate-secrets" '' - export PATH=${lib.makeBinPath [ coreutils pwgen openssl gnugrep rpcauth ]} - . ${./generate-secrets.sh} ${./openssl.cnf} -'' diff --git a/pkgs/generate-secrets/generate-secrets.sh b/pkgs/generate-secrets/generate-secrets.sh deleted file mode 100755 index 6def36b..0000000 --- a/pkgs/generate-secrets/generate-secrets.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -opensslConf=${1:-openssl.cnf} - -makePasswordSecret() { - # Passwords have alphabet {a-z, A-Z, 0-9} and ~119 bits of entropy - [[ -e $1 ]] || pwgen -s 20 1 > "$1" -} -makeHMAC() { - user=$1 - rpcauth $user $(cat bitcoin-rpcpassword-$user) | grep rpcauth | cut -d ':' -f 2 > bitcoin-HMAC-$user -} - -makePasswordSecret bitcoin-rpcpassword-privileged -makePasswordSecret bitcoin-rpcpassword-btcpayserver -makePasswordSecret bitcoin-rpcpassword-joinmarket-ob-watcher -makePasswordSecret bitcoin-rpcpassword-public -makePasswordSecret lnd-wallet-password -makePasswordSecret liquid-rpcpassword -makePasswordSecret spark-wallet-password -makePasswordSecret backup-encryption-password -makePasswordSecret jm-wallet-password - -[[ -e bitcoin-HMAC-privileged ]] || makeHMAC privileged -[[ -e bitcoin-HMAC-public ]] || makeHMAC public -[[ -e bitcoin-HMAC-btcpayserver ]] || makeHMAC btcpayserver -[[ -e bitcoin-HMAC-joinmarket-ob-watcher ]] || makeHMAC joinmarket-ob-watcher -[[ -e spark-wallet-login ]] || echo "login=spark-wallet:$(cat spark-wallet-password)" > spark-wallet-login -[[ -e backup-encryption-env ]] || echo "PASSPHRASE=$(cat backup-encryption-password)" > backup-encryption-env - -makeCert() { - if [[ ! -e $name-key || ! -e $name-cert ]]; then - openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \ - -sha256 -days 3650 -nodes -keyout "$name-key" -out "$name-cert" \ - -subj "/CN=localhost/O=$name" \ - -addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:169.254.1.14,IP:169.254.1.22" - # TODO: Remove hardcoded lnd, loopd netns ips - fi -} - -makeCert lnd -makeCert loop diff --git a/pkgs/generate-secrets/update-and-generate.nix b/pkgs/generate-secrets/update-and-generate.nix deleted file mode 100644 index c2cfae9..0000000 --- a/pkgs/generate-secrets/update-and-generate.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ pkgs }: with pkgs; - -let - generate-secrets = callPackage ./. {}; -in -writeScript "make-secrets" '' - # Update from old secrets format - [[ -e secrets.nix ]] && . ${./update-secrets.sh} - ${generate-secrets} -'' diff --git a/pkgs/generate-secrets/update-secrets.sh b/pkgs/generate-secrets/update-secrets.sh deleted file mode 100644 index 6d9ed10..0000000 --- a/pkgs/generate-secrets/update-secrets.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash - -set -eo pipefail - -# Update secrets from the old format to the current one where each secret -# has a local source file. - -reportError() { - echo "Updating secrets failed. (Error in line $1)" - echo "The secret files have been moved to secrets/old-secrets" -} -trap 'reportError $LINENO' ERR - -echo "Updating old secrets to the current format." - -mkdir old-secrets -# move all files into old-secrets -shopt -s extglob dotglob -mv !(old-secrets) old-secrets -shopt -u dotglob - -secrets=$(cat old-secrets/secrets.nix) - -extractPassword() { - pwName="$1" - destFile="${2:-$pwName}" - echo "$secrets" | sed -nE "s/.*?$pwName = \"(.*?)\".*/\1/p" > "$destFile" -} - -rename() { - old="old-secrets/$1" - if [[ -e $old ]]; then - cp "$old" "$2" - fi -} - -extractPassword bitcoinrpcpassword bitcoin-rpcpassword -extractPassword lnd-wallet-password -extractPassword liquidrpcpassword liquid-rpcpassword -extractPassword spark-wallet-password - -rename lnd.key lnd-key -rename lnd.cert lnd-cert - -rm -r old-secrets From fdcb68e96efed9b9210687f2fd02cf810edd21b7 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Wed, 8 Sep 2021 17:01:19 +0200 Subject: [PATCH 11/11] examples/shell.nix: add new commands --- helper/makeShell.nix | 59 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/helper/makeShell.nix b/helper/makeShell.nix index 0fbd24b..c674d82 100644 --- a/helper/makeShell.nix +++ b/helper/makeShell.nix @@ -17,10 +17,41 @@ stdenv.mkDerivation rec { export NIX_BITCOIN_EXAMPLES_DIR="${cfgDir}" + help() { + echo "nix-bitcoin path: ${toString ../.}" + echo + echo "Available commands" + echo "==================" + echo "deploy" + echo " Run krops-deploy and eval-config in parallel." + echo " This ensures that eval failures appear quickly when deploying." + echo " In this case, deployment is stopped." + echo + echo "krops-deploy" + echo " Deploy your node via krops" + echo + echo "eval-config" + echo " Evaluate your node system configuration" + echo + echo "generate-secrets" + echo " Create secrets required by your node configuration." + echo " Secrets are written to ./secrets/" + echo " This function is automatically called by krops-deploy." + echo + echo "update-nix-bitcoin" + echo " Fetch and use the latest version of nix-bitcoin" + } + h() { help; } + fetch-release() { ${toString ./fetch-release} } + update-nix-bitcoin() { + fetch-release > "${cfgDir}/nix-bitcoin-release.nix" + exec nix-shell + } + generate-secrets() {( set -euo pipefail genSecrets=$(nix-build --no-out-link -I nixos-config="${cfgDir}/configuration.nix" \ @@ -29,6 +60,19 @@ stdenv.mkDerivation rec { (cd "${cfgDir}/secrets"; $genSecrets) )} + deploy() {( + set -euo pipefail + krops-deploy & + kropsPid=$! + if eval-config; then + wait $kropsPid + else + # Kill all subprocesses + kill $(pidClosure $kropsPid) + return 1 + fi + )} + krops-deploy() {( set -euo pipefail generate-secrets @@ -38,11 +82,24 @@ stdenv.mkDerivation rec { $(nix-build --no-out-link "${cfgDir}/krops/deploy.nix") )} - # Print logo if + eval-config() { + NIXOS_CONFIG="${cfgDir}/krops/krops-configuration.nix" nix eval --raw -f ${nixpkgs}/nixos system.outPath + echo + } + + pidClosure() { + echo "$1" + for pid in $(ps -o pid= --ppid "$1"); do + pidClosure "$pid" + done + } + + # Print welcome message if # 1. stdout is a TTY, i.e. we're not piping the output # 2. the shell is interactive if [[ -t 1 && $- == *i* ]]; then ${figlet}/bin/figlet "nix-bitcoin" + echo 'Enter "h" or "help" for documentation.' fi # Don't run this hook when another nix-shell is run inside this shell