From 28d0a72c628361642fe5e338081d42d496903d9f Mon Sep 17 00:00:00 2001 From: Colin Date: Tue, 2 Jan 2024 14:29:52 +0000 Subject: [PATCH] define (but dont activate) a clighting bitcoin service --- modules/services/clightning.nix | 161 ++++++++++++++++++++++++++++++++ modules/services/default.nix | 1 + 2 files changed, 162 insertions(+) create mode 100644 modules/services/clightning.nix diff --git a/modules/services/clightning.nix b/modules/services/clightning.nix new file mode 100644 index 00000000..76628cd2 --- /dev/null +++ b/modules/services/clightning.nix @@ -0,0 +1,161 @@ +# clightning: Bitcoin Lightning Network daemon +# +# module is based on nix-bitcoin: +# +# reasons to prefer this module over nix-bitcoin's include: +# - compatible with nixpkgs' bitcoind service +# - more self-contained +# - doesn't pull in an entire nix secrets management implementation +# although that can be disabled with `nix-bitcoin.secretsSetupMethod = "manual"` +# +{ config, lib, pkgs, ... }: + +let + cfg = config.sane.services.clightning; + bitcoind = config.services.bitcoind."${cfg.bitcoindName}"; + # clightning config docs: + configFile = pkgs.writeText "config" '' + network=bitcoin + bitcoin-datadir=${bitcoind.dataDir} + ${lib.optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"} + always-use-proxy=${lib.boolToString cfg.always-use-proxy} + bind-addr=${cfg.address}:${toString cfg.port} + bitcoin-rpcconnect=127.0.0.1 + bitcoin-rpcport=8332 + bitcoin-rpcuser=${cfg.user} + rpc-file-mode=0660 + log-timestamps=false + ${cfg.extraConfig} + ''; +in +{ + options = with lib; { + sane.services.clightning = { + enable = mkEnableOption "clightning, a Lightning Network implementation in C"; + package = mkPackageOption pkgs "clightning" { }; + bitcoindName = mkOption { + type = str; + default = "mainnet"; + description = '' + name of bitcoind config to attach to. + for example if you configured `services.bitcoind.mainnet`, then specify "mainnet" here. + ''; + }; + + user = mkOption { + type = types.str; + default = "clightning"; + description = mdDoc "The user as which to run clightning."; + }; + group = mkOption { + type = types.str; + default = cfg.user; + description = mdDoc "The group as which to run clightning."; + }; + dataDir = mkOption { + type = types.path; + default = "/var/lib/clightning"; + description = mdDoc "The data directory for clightning."; + }; + networkDir = mkOption { + type = types.path; + default = "${cfg.dataDir}/bitcoin"; + description = mdDoc "The network data directory."; + }; + + address = mkOption { + type = types.str; + default = "127.0.0.1"; + description = mdDoc "Address to listen for peer connections."; + }; + port = mkOption { + type = types.port; + default = 9735; + description = mdDoc "Port to listen for peer connections."; + }; + proxy = mkOption { + type = types.nullOr types.str; + default = null; + description = mdDoc '' + Socks proxy for connecting to Tor nodes (or for all connections if option always-use-proxy is set). + ''; + }; + always-use-proxy = mkOption { + type = types.bool; + default = cfg.proxy != null; + description = mdDoc '' + Always use the proxy, even to connect to normal IP addresses. + You can still connect to Unix domain sockets manually. + This also disables all DNS lookups, to avoid leaking address information. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + alias=mynode + ''; + description = mdDoc '' + Extra lines appended to the configuration file. + + See all available options at + https://github.com/ElementsProject/lightning/blob/master/doc/lightningd-config.5.md + or by running {command}`lightningd --help`. + ''; + }; + extraConfigFiles = mkOption { + type = types.listOf types.str; + default = []; + description = '' + extra files to populate the config from at runtime. + useful if you need to pass config you wish to keep outside the nix store, such as secrets. + + you should probably populate this with a file that defines + bitcoin-rpcpassword=MY_HASHED_RPCAUTH_PASSWORD + ''; + }; + }; + }; + config = lib.mkIf cfg.enable { + systemd.services.clightning = { + path = [ bitcoind.package ]; + wantedBy = [ "multi-user.target" ]; + requires = [ "bitcoind-${cfg.bitcoindName}.service" ]; + after = [ "bitcoind-${cfg.bitcoindName}.service" ]; + + serviceConfig = { + ExecStart = "${cfg.package}/bin/lightningd --lightning-dir=${cfg.dataDir}"; + User = cfg.user; + Restart = "on-failure"; + RestartSec = "30s"; + ReadWritePaths = [ cfg.dataDir ]; + }; + + preStart = '' + # Remove an existing socket so that `postStart` can detect when a new + # socket has been created and clightning is ready to accept RPC connections. + # This will no longer be needed when clightning supports systemd startup notifications. + rm -f ${cfg.networkDir}/lightning-rpc + + umask u=rw,g=r,o= + cat ${configFile} ${lib.concatStringsSep " " cfg.extraConfigFiles} > ${cfg.dataDir}/config + ''; + # Wait until the rpc socket appears + postStart = '' + while [[ ! -e ${cfg.networkDir}/lightning-rpc ]]; do + sleep 0.1 + done + # Needed to enable lightning-cli for users with group 'clightning' + chmod g+x ${cfg.networkDir} + ''; + }; + + users.users.${cfg.user} = { + isSystemUser = true; + group = cfg.group; + extraGroups = [ "bitcoind-${cfg.bitcoindName}" ]; + }; + users.groups.${cfg.group} = {}; + }; +} diff --git a/modules/services/default.nix b/modules/services/default.nix index 556901bf..74a6e89a 100644 --- a/modules/services/default.nix +++ b/modules/services/default.nix @@ -1,6 +1,7 @@ { ... }: { imports = [ + ./clightning.nix ./dyn-dns.nix ./eg25-control.nix ./eg25-manager.nix