diff --git a/modules/lightning-loop.nix b/modules/lightning-loop.nix index 00da742..1bd526c 100644 --- a/modules/lightning-loop.nix +++ b/modules/lightning-loop.nix @@ -40,13 +40,37 @@ let default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null; description = "host:port of SOCKS5 proxy for connnecting to the loop server."; }; + certificate = { + extraIPs = mkOption { + type = with types; listOf str; + default = []; + example = [ "60.100.0.1" ]; + description = '' + Extra `subjectAltName` IPs added to the certificate. + This works the same as loop option `tlsextraip`. + ''; + }; + extraDomains = mkOption { + type = with types; listOf str; + default = []; + example = [ "example.com" ]; + description = '' + Extra `subjectAltName` domain names added to the certificate. + This works the same as loop option `tlsextradomain`. + ''; + }; + }; extraConfig = mkOption { type = types.lines; default = ""; example = '' debuglevel=trace ''; - description = "Extra lines appended to the configuration file."; + description = '' + Extra lines appended to the configuration file. + See here for all available options: + https://github.com/lightninglabs/loop/blob/11ab596080e9d36f1df43edbeba0702b25aa7457/loopd/config.go#L119 + ''; }; cli = mkOption { default = pkgs.writeScriptBin "loop" '' @@ -97,6 +121,8 @@ in { "d '${cfg.dataDir}' 0770 ${lnd.user} ${lnd.group} - -" ]; + services.lightning-loop.certificate.extraIPs = mkIf (cfg.rpcAddress != "localhost") [ "${cfg.rpcAddress}" ]; + systemd.services.lightning-loop = { wantedBy = [ "multi-user.target" ]; requires = [ "lnd.service" ]; @@ -115,7 +141,7 @@ in { loop-cert.user = lnd.user; }; nix-bitcoin.generateSecretsCmds.lightning-loop = '' - makeCert loop '${optionalString (cfg.rpcAddress != "localhost") "IP:${cfg.rpcAddress}"}' + makeCert loop '${nbLib.mkCertExtraAltNames cfg.certificate}' ''; }; } diff --git a/modules/lnd.nix b/modules/lnd.nix index 25e26c6..8e57a1f 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -70,13 +70,37 @@ let Extra macaroon definitions. ''; }; + certificate = { + extraIPs = mkOption { + type = with types; listOf str; + default = []; + example = [ "60.100.0.1" ]; + description = '' + Extra `subjectAltName` IPs added to the certificate. + This works the same as lnd option `tlsextraip`. + ''; + }; + extraDomains = mkOption { + type = with types; listOf str; + default = []; + example = [ "example.com" ]; + description = '' + Extra `subjectAltName` domain names added to the certificate. + This works the same as lnd option `tlsextradomain`. + ''; + }; + }; extraConfig = mkOption { type = types.lines; default = ""; example = '' autopilot.active=1 ''; - description = "Extra lines appended to lnd.conf."; + description = '' + Extra lines appended to `lnd.conf`. + See here for all available options: + https://github.com/lightningnetwork/lnd/blob/master/sample-lnd.conf + ''; }; package = mkOption { type = types.package; @@ -191,6 +215,8 @@ in { "d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -" ]; + services.lnd.certificate.extraIPs = mkIf (cfg.rpcAddress != "localhost") [ "${cfg.rpcAddress}" ]; + systemd.services.lnd = { wantedBy = [ "multi-user.target" ]; requires = [ "bitcoind.service" ]; @@ -278,7 +304,7 @@ in { # - 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}"}' + makeCert lnd '${nbLib.mkCertExtraAltNames cfg.certificate}' ''; }; } diff --git a/pkgs/lib.nix b/pkgs/lib.nix index ff4d44f..07a105d 100644 --- a/pkgs/lib.nix +++ b/pkgs/lib.nix @@ -109,4 +109,10 @@ let self = { optionalAttr = cond: name: if cond then name else null; + mkCertExtraAltNames = cert: + builtins.concatStringsSep "," ( + (map (domain: "DNS:${domain}") cert.extraDomains) ++ + (map (ip: "IP:${ip}") cert.extraIPs) + ); + }; in self diff --git a/test/tests.nix b/test/tests.nix index 77e367a..7eccd08 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -35,6 +35,13 @@ let # Share the same pkgs instance among tests nixpkgs.pkgs = mkDefault globalPkgs; + environment.systemPackages = mkMerge (with pkgs; [ + # Needed to test macaroon creation + (mkIfTest "btcpayserver" [ openssl xxd ]) + # Needed to test certificate creation + (mkIfTest "lnd" [ openssl ]) + ]); + tests.bitcoind = cfg.bitcoind.enable; services.bitcoind = { enable = true; @@ -81,12 +88,19 @@ let tests.spark-wallet = cfg.spark-wallet.enable; tests.lnd = cfg.lnd.enable; - services.lnd.port = 9736; + services.lnd = { + port = 9736; + certificate = { + extraIPs = [ "10.0.0.1" "20.0.0.1" ]; + extraDomains = [ "example.com" ]; + }; + }; tests.lndconnect-onion-lnd = cfg.lnd.lndconnectOnion.enable; tests.lndconnect-onion-clightning = cfg.clightning-rest.lndconnectOnion.enable; tests.lightning-loop = cfg.lightning-loop.enable; + services.lightning-loop.certificate.extraIPs = [ "20.0.0.1" ]; tests.lightning-pool = cfg.lightning-pool.enable; nix-bitcoin.onionServices.lnd.public = true; @@ -103,8 +117,6 @@ let lightningBackend = mkDefault "lnd"; lbtc = mkDefault true; }; - # Needed to test macaroon creation - environment.systemPackages = mkIfTest "btcpayserver" (with pkgs; [ openssl xxd ]); test.data.btcpayserver-lbtc = config.services.btcpayserver.lbtc; tests.joinmarket = cfg.joinmarket.enable; diff --git a/test/tests.py b/test/tests.py index 3b20aa1..35ce34b 100644 --- a/test/tests.py +++ b/test/tests.py @@ -7,9 +7,11 @@ def succeed(*cmds): return machine.succeed(*cmds) def assert_matches(cmd, regexp): - out = succeed(cmd) - if not re.search(regexp, out): - raise Exception(f"Pattern '{regexp}' not found in '{out}'") + assert_str_matches(succeed(cmd), regexp) + +def assert_str_matches(str, regexp): + if not re.search(regexp, str): + raise Exception(f"Pattern '{regexp}' not found in '{str}'") def assert_full_match(cmd, regexp): out = succeed(cmd) @@ -152,6 +154,12 @@ def _(): assert_matches("runuser -u operator -- lncli getinfo | jq", '"version"') assert_no_failure("lnd") + # Test certificate generation + cert_alt_names = succeed("