{ config, lib, pkgs, ... }: with lib; let options.services.blockstream-electrs = { enable = mkEnableOption "Blockstream electrs, an Electrum server implemented in Rust, modified for use by Blockstream esplora"; address = mkOption { type = types.str; default = "127.0.0.1"; description = mdDoc "Address to listen for RPC connections."; }; port = mkOption { type = types.port; default = 50001; description = mdDoc "Port to listen for RPC connections."; }; dataDir = mkOption { type = types.path; default = "/var/lib/blockstream-electrs"; description = mdDoc "The data directory for electrs."; }; monitoringPort = mkOption { type = types.port; default = 4224; description = mdDoc "Prometheus monitoring port."; }; extraArgs = mkOption { type = types.separatedString " "; default = ""; description = mdDoc "Extra command line arguments passed to electrs."; }; user = mkOption { type = types.str; default = "blockstream-electrs"; description = mdDoc "The user as which to run electrs."; }; group = mkOption { type = types.str; default = config.services.blockstream-electrs.user; description = mdDoc "The group as which to run electrs."; }; tor.enforce = nbLib.tor.enforce; }; # config.services.blockstream-electrs = config.services.blockstream-electrs; nbLib = config.nix-bitcoin.lib; secretsDir = config.nix-bitcoin.secretsDir; bitcoind = config.services.bitcoind; in { inherit options; config = mkIf config.services.blockstream-electrs.enable { assertions = [ { assertion = bitcoind.prune == 0; message = "electrs does not support bitcoind pruning."; } ]; services.bitcoind = { enable = true; listenWhitelisted = true; }; systemd.tmpfiles.rules = [ "d '${config.services.blockstream-electrs.dataDir}' 0770 ${config.services.blockstream-electrs.user} ${config.services.blockstream-electrs.group} - -" ]; systemd.services.blockstream-electrs = { wantedBy = [ "multi-user.target" ]; requires = [ "bitcoind.service" ]; after = [ "bitcoind.service" ]; preStart = '' echo "auth = \"${bitcoind.rpc.users.public.name}:$(cat ${secretsDir}/bitcoin-rpcpassword-public)\"" \ > electrs.toml ''; serviceConfig = nbLib.defaultHardening // { # electrs only uses the working directory for reading electrs.toml WorkingDirectory = config.services.blockstream-electrs.dataDir; ExecStart = '' ${config.pkgs.blockstream-electrs}/bin/electrs \ --log-filters=INFO \ --network=${bitcoind.makeNetworkName "bitcoin" "regtest"} \ --db-dir='${config.services.blockstream-electrs.dataDir}' \ --daemon-dir='${bitcoind.dataDir}' \ --electrum-rpc-addr=${config.services.blockstream-electrs.address}:${toString config.services.blockstream-electrs.port} \ --monitoring-addr=${config.services.blockstream-electrs.address}:${toString config.services.blockstream-electrs.monitoringPort} \ --daemon-rpc-addr=${nbLib.addressWithPort bitcoind.rpc.address bitcoind.rpc.port} \ --daemon-p2p-addr=${nbLib.addressWithPort bitcoind.address bitcoind.whitelistedPort} \ ${config.services.blockstream-electrs.extraArgs} ''; User = config.services.blockstream-electrs.user; Group = config.services.blockstream-electrs.group; Restart = "on-failure"; RestartSec = "10s"; ReadWritePaths = [ config.services.blockstream-electrs.dataDir ]; } // nbLib.allowedIPAddresses config.services.blockstream-electrs.tor.enforce; }; users.users.${config.services.blockstream-electrs.user} = { isSystemUser = true; group = config.services.blockstream-electrs.group; extraGroups = [ "bitcoinrpc-public" ]; }; users.groups.${config.services.blockstream-electrs.group} = {}; }; }