diff --git a/README.md b/README.md index 1b51aa0ec..3775709c9 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ NixOS modules ([src](modules/modules.nix)) * [Lightning Pool](https://github.com/lightninglabs/pool) * [charge-lnd](https://github.com/accumulator/charge-lnd): policy-based channel fee manager * [lndconnect](https://github.com/LN-Zap/lndconnect): connect your wallet to lnd or clightning via a REST onion service + * [LndHub.go](https://github.com/getAlby/lndhub.go): an accounting wrapper for the Lightning Network * [Ride The Lightning](https://github.com/Ride-The-Lightning/RTL): web interface for `lnd` and `clightning` * [spark-wallet](https://github.com/shesek/spark-wallet) * [electrs](https://github.com/romanz/electrs) diff --git a/examples/configuration.nix b/examples/configuration.nix index 9ec5837f8..0137bb787 100644 --- a/examples/configuration.nix +++ b/examples/configuration.nix @@ -136,6 +136,11 @@ # # services.fulcrum.enable = true; + ### LNDHUB.GO + # Set this to enable LndHub.go, an accounting wrapper for the Lightning Network. + # + # services.lndhub-go.enable = true; + ### BTCPayServer # Set this to enable BTCPayServer, a self-hosted, open-source # cryptocurrency payment processor. diff --git a/modules/default.nix b/modules/default.nix index f173f9ac5..6f10628fe 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -7,6 +7,7 @@ liquid = ./liquid.nix; presets.secure-node = ./presets/secure-node.nix; rtl = ./rtl.nix; + lndhub-go = ./lndhub-go.nix; spark-wallet = ./spark-wallet.nix; lnd = ./lnd.nix; charge-lnd = ./charge-lnd.nix; diff --git a/modules/lndhub-go.nix b/modules/lndhub-go.nix new file mode 100644 index 000000000..d00b87294 --- /dev/null +++ b/modules/lndhub-go.nix @@ -0,0 +1,136 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + options.services = { + lndhub-go = { + enable = mkEnableOption "LndHub.go, an accounting wrapper for the Lightning Network"; + address = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "Address to listen on."; + }; + port = mkOption { + type = types.port; + default = 8082; + description = "Port to listen on."; + }; + settings = mkOption { + type = with types; attrsOf (oneOf [ str int bool ]); + example = { + ALLOW_ACCOUNT_CREATION = false; + FEE_RESERVE = true; + MAX_SEND_AMOUNT = 1000000; + }; + description = '' + LndHub.go settings. + See here for possible options: + https://github.com/getAlby/lndhub.go#available-configuration + ''; + }; + package = mkOption { + type = types.package; + default = config.nix-bitcoin.pkgs.lndhub-go; + defaultText = "config.nix-bitcoin.pkgs.lndhub-go"; + description = "The package providing LndHub.go binaries."; + }; + dataDir = mkOption { + type = types.path; + default = "/var/lib/lndhub-go"; + description = "The data directory for LndHub.go."; + }; + user = mkOption { + type = types.str; + default = "lndhub-go"; + description = "The user as which to run LndHub.go."; + }; + group = mkOption { + type = types.str; + default = cfg.user; + description = "The group as which to run LndHub.go."; + }; + tor.enforce = nbLib.tor.enforce; + }; + }; + + cfg = config.services.lndhub-go; + nbLib = config.nix-bitcoin.lib; + + inherit (config.services) + lnd + postgresql; + + configFile = builtins.toFile "lndhub-go-conf" (lib.generators.toKeyValue {} cfg.settings); + + dbName = "lndhubgo"; +in { + inherit options; + + config = mkIf cfg.enable { + services.lnd = { + enable = true; + macaroons.lndhub-go = { + inherit (cfg) user; + permissions = ''{"entity":"info","action":"read"},{"entity":"invoices","action":"read"},{"entity":"invoices","action":"write"},{"entity":"offchain","action":"read"},{"entity":"offchain","action":"write"}''; + }; + }; + services.postgresql = { + enable = true; + ensureDatabases = [ dbName ]; + ensureUsers = [ + { + name = cfg.user; + ensurePermissions."DATABASE ${dbName}" = "ALL PRIVILEGES"; + } + ]; + }; + + services.lndhub-go.settings = { + HOST = cfg.address; + PORT = cfg.port; + DATABASE_URI = "unix://${cfg.user}@${dbName}/run/postgresql/.s.PGSQL.${toString postgresql.port}?sslmode=disable"; + LND_ADDRESS = "${nbLib.addressWithPort lnd.address lnd.port}"; + LND_MACAROON_FILE = "/run/lnd/lndhub-go.macaroon"; + LND_CERT_FILE = lnd.certPath; + BRANDING_TITLE = "LndHub.go - Nix-Bitcoin"; + BRANDING_DESC = "Accounting wrapper for the Lightning Network"; + BRANDING_URL = "https://nixbitcoin.org"; + BRANDING_LOGO = "https://nixbitcoin.org/files/nix-bitcoin-logo-text.png"; + BRANDING_FAVICON = "https://nixbitcoin.org/files/nix-bitcoin-logo.png"; + BRANDING_FOOTER = "about=https://nixbitcoin.org;github=https://github.com/fort-nix/nix-bitcoin"; + }; + + systemd.services.lndhub-go = rec { + wantedBy = [ "multi-user.target" ]; + requires = [ "lnd.service" "postgresql.service" ]; + after = requires; + preStart = '' + set -euo pipefail + { + cat ${configFile} + echo "JWT_SECRET=$(cat '${config.nix-bitcoin.secretsDir}/lndhub.go-jwt-secret')" + } > .env + ''; + serviceConfig = nbLib.defaultHardening // { + StateDirectory = "lndhub-go"; + StateDirectoryMode = "770"; + WorkingDirectory = "/var/lib/lndhub-go"; + ExecStart = "${config.nix-bitcoin.pkgs.lndhub-go}/bin/lndhub.go"; + User = cfg.user; + Restart = "on-failure"; + RestartSec = "10s"; + } // nbLib.allowedIPAddresses cfg.tor.enforce; + }; + + users.users.${cfg.user} = { + isSystemUser = true; + group = cfg.group; + }; + users.groups.${cfg.group} = {}; + + nix-bitcoin.secrets."lndhub.go-jwt-secret".user = cfg.user; + nix-bitcoin.generateSecretsCmds.lndhub-go = '' + makePasswordSecret lndhub.go-jwt-secret + ''; + }; +} diff --git a/modules/modules.nix b/modules/modules.nix index fd3907769..297c3b634 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -16,6 +16,7 @@ ./clightning-replication.nix ./spark-wallet.nix ./lnd.nix + ./lndhub-go.nix ./lightning-loop.nix ./lightning-pool.nix ./charge-lnd.nix diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix index 940a8c682..226bbb783 100644 --- a/modules/netns-isolation.nix +++ b/modules/netns-isolation.nix @@ -297,6 +297,10 @@ in { id = 31; connections = [ "bitcoind" ]; }; + lndhub-go = { + id = 32; + connections = [ "lnd" ]; + }; }; services.bitcoind = { @@ -355,6 +359,8 @@ in { services.rtl.address = netns.rtl.address; services.clightning-rest.address = netns.clightning-rest.address; + + services.lndhub-go.address = netns.lndhub-go.address; } ]); } diff --git a/modules/nodeinfo.nix b/modules/nodeinfo.nix index e6adba295..e4d7ab242 100644 --- a/modules/nodeinfo.nix +++ b/modules/nodeinfo.nix @@ -138,6 +138,7 @@ in { liquidd = mkInfo ""; joinmarket-ob-watcher = mkInfo ""; rtl = mkInfo ""; + lndhub-go = mkInfo ""; # Only add sshd when it has an onion service sshd = name: cfg: mkIfOnionPort "sshd" (onionPort: '' add_service("sshd", """set_onion_address(info, "sshd", ${onionPort})""") diff --git a/modules/presets/enable-tor.nix b/modules/presets/enable-tor.nix index 709c01e6b..108dc937b 100644 --- a/modules/presets/enable-tor.nix +++ b/modules/presets/enable-tor.nix @@ -40,6 +40,7 @@ in { joinmarket = defaultEnforceTor; joinmarket-ob-watcher = defaultEnforceTor; clightning-rest = defaultEnforceTor; + lndhub-go = defaultEnforceTor; }; # Add onion services for incoming connections @@ -51,5 +52,6 @@ in { spark-wallet.enable = defaultTrue; joinmarket-ob-watcher.enable = defaultTrue; rtl.enable = defaultTrue; + lndhub-go.enable = defaultTrue; }; } diff --git a/pkgs/pinned.nix b/pkgs/pinned.nix index 91629b33d..9b15ae092 100644 --- a/pkgs/pinned.nix +++ b/pkgs/pinned.nix @@ -17,7 +17,8 @@ pkgs: pkgsUnstable: fulcrum hwi lightning-loop - lnd; + lnd + lndhub-go; inherit pkgs pkgsUnstable; } diff --git a/test/tests.nix b/test/tests.nix index 1d74b4025..174b49603 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -118,6 +118,8 @@ let tests.liquidd = cfg.liquidd.enable; services.liquidd.extraConfig = mkIf config.test.noConnections "connect=0"; + tests.lndhub-go = cfg.lndhub-go.enable; + tests.btcpayserver = cfg.btcpayserver.enable; services.btcpayserver = { lightningBackend = mkDefault "lnd"; @@ -204,6 +206,7 @@ let services.lightning-loop.enable = true; services.lightning-pool.enable = true; services.charge-lnd.enable = true; + services.lndhub-go.enable = true; services.electrs.enable = true; services.fulcrum.enable = true; services.liquidd.enable = true; @@ -251,6 +254,7 @@ let services.lightning-loop.enable = true; services.lightning-pool.enable = true; services.charge-lnd.enable = true; + services.lndhub-go.enable = true; services.electrs.enable = true; services.fulcrum.enable = true; services.btcpayserver.enable = true; diff --git a/test/tests.py b/test/tests.py index 1fb98e24d..66baf0610 100644 --- a/test/tests.py +++ b/test/tests.py @@ -123,6 +123,11 @@ def _(): def _(): succeed("systemctl stop electrs") +@test("lndhub-go") +def _(): + assert_running("lndhub-go") + wait_for_open_port(ip("lndhub-go"), 8082) + @test("liquidd") def _(): assert_running("liquidd")