Add Carl's bitcoind module

This commit is contained in:
Jonas Nick 2018-11-23 00:46:56 +00:00
parent 79aab1255a
commit b1375df03a
4 changed files with 204 additions and 69 deletions

View File

@ -40,10 +40,6 @@ in {
# networking.firewall.allowedUDPPorts = [ ... ]; # networking.firewall.allowedUDPPorts = [ ... ];
networking.firewall.enable = true; networking.firewall.enable = true;
services.bitcoin.enable = true;
# make an onion listen node
services.tor.enable = true;
services.tor.client.enable = true;
#services.bitcoin.proxy = services.tor.client.socksListenAddress; #services.bitcoin.proxy = services.tor.client.socksListenAddress;
services.nixbitcoin.enable = true; services.nixbitcoin.enable = true;

View File

@ -1,85 +1,226 @@
{ config, lib, pkgs, ... }: { config, pkgs, lib, ... }:
with lib; with lib;
let let
cfg = config.services.bitcoin; cfg = config.services.bitcoind;
home = "/var/lib/bitcoin"; pidFile = "${cfg.dataDir}/bitcoind.pid";
configFile = pkgs.writeText "bitcoin.conf" '' configFile = pkgs.writeText "bitcoin.conf" ''
listen=${if cfg.listen then "1" else "0"} ${optionalString cfg.testnet "testnet=1"}
prune=2000 ${optionalString (cfg.dbCache != null) "dbcache=${toString cfg.dbCache}"}
assumevalid=0000000000000000000726d186d6298b5054b9a5c49639752294b322a305d240 ${optionalString (cfg.prune != null) "prune=${toString cfg.prune}"}
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
addnode=ecoc5q34tmbq54wl.onion # Connection options
discover=0
${optionalString (cfg.port != null) "port=${toString cfg.port}"} ${optionalString (cfg.port != null) "port=${toString cfg.port}"}
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
listen=${if cfg.listen then "1" else "0"}
# RPC server options
${optionalString (cfg.rpc.port != null) "rpcport=${toString cfg.rpc.port}"}
${concatMapStringsSep "\n"
(rpcUser: "rpcauth=${rpcUser.name}:${rpcUser.passwordHMAC}")
(attrValues cfg.rpc.users)
}
${optionalString (cfg.rpcuser != null) "rpcuser=${cfg.rpcuser}"} ${optionalString (cfg.rpcuser != null) "rpcuser=${cfg.rpcuser}"}
${optionalString (cfg.rpcpassword != null) "rpcpassword=${cfg.rpcpassword}"} ${optionalString (cfg.rpcpassword != null) "rpcpassword=${cfg.rpcpassword}"}
'';
# Extra config options (from bitcoind nixos service)
${cfg.extraConfig}
'';
cmdlineOptions = concatMapStringsSep " " (arg: "'${arg}'") [
"-conf=${configFile}"
"-datadir=${cfg.dataDir}"
"-pid=${pidFile}"
];
hexStr = types.strMatching "[0-9a-f]+";
rpcUserOpts = { name, ... }: {
options = {
name = mkOption {
type = types.str;
example = "alice";
description = ''
Username for JSON-RPC connections.
'';
};
passwordHMAC = mkOption {
type = with types; uniq (strMatching "[0-9a-f]+\\$[0-9a-f]{64}");
example = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
description = ''
Password HMAC-SHA-256 for JSON-RPC connections. Must be a string of the
format <SALT-HEX>$<HMAC-HEX>.
'';
};
};
config = {
name = mkDefault name;
};
};
in { in {
options.services.bitcoin = { options = {
enable = mkOption {
type = types.bool; services.bitcoind = {
default = false; enable = mkEnableOption "Bitcoin daemon";
description = ''
If enabled, the bitcoin service will be installed. package = mkOption {
''; type = types.package;
}; default = pkgs.altcoins.bitcoind;
listen = mkOption { defaultText = "pkgs.altcoins.bitcoind";
type = types.bool; description = "The package providing bitcoin binaries.";
default = false; };
description = '' extraConfig = mkOption {
If enabled, the bitcoin service will listen. type = types.lines;
''; default = "";
}; example = ''
proxy = mkOption { par=16
type = types.nullOr types.string; rpcthreads=16
default = null; logips=1
description = '' assumevalid=0000000000000000000726d186d6298b5054b9a5c49639752294b322a305d240
proxy addnode=ecoc5q34tmbq54wl.onion
''; discover=0
}; printtoconsole=1
port = mkOption { '';
description = "Additional configurations to be appended to <filename>bitcoin.conf</filename>.";
};
dataDir = mkOption {
type = types.path;
default = "/var/lib/bitcoind";
description = "The data directory for bitcoind.";
};
user = mkOption {
type = types.str;
default = "bitcoin";
description = "The user as which to run bitcoind.";
};
group = mkOption {
type = types.str;
default = cfg.user;
description = "The group as which to run bitcoind.";
};
rpc = {
port = mkOption {
type = types.nullOr types.ints.u16;
default = null;
description = "Override the default port on which to listen for JSON-RPC connections.";
};
users = mkOption {
default = {};
example = {
alice.passwordHMAC = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
bob.passwordHMAC = "b2dd077cb54591a2f3139e69a897ac$4e71f08d48b4347cf8eff3815c0e25ae2e9a4340474079f55705f40574f4ec99";
};
type = with types; loaOf (submodule rpcUserOpts);
description = ''
RPC user information for JSON-RPC connnections.
'';
};
};
rpcuser = mkOption {
type = types.nullOr types.string;
default = null;
description = "Username for JSON-RPC connections";
};
rpcpassword = mkOption {
type = types.nullOr types.string;
default = null;
description = "Password for JSON-RPC connections";
};
testnet = mkOption {
type = types.bool;
default = false;
description = "Whether to use the test chain.";
};
port = mkOption {
type = types.nullOr types.ints.u16; type = types.nullOr types.ints.u16;
default = null; default = null;
description = "Override the default port on which to listen for connections."; description = "Override the default port on which to listen for connections.";
}; };
rpcuser = mkOption { proxy = mkOption {
type = types.nullOr types.string; type = types.nullOr types.string;
default = null; default = null;
description = "Set bitcoin RPC user"; description = "Connect through SOCKS5 proxy";
}; };
rpcpassword = mkOption { listen = mkOption {
type = types.nullOr types.string; type = types.bool;
default = false;
description = ''
If enabled, the bitcoin service will listen.
'';
};
dbCache = mkOption {
type = types.nullOr (types.ints.between 4 16384);
default = null; default = null;
description = "Set bitcoin RPC password"; example = 4000;
description = "Override the default database cache size in megabytes.";
};
prune = mkOption {
type = types.nullOr (types.coercedTo
(types.enum [ "disable" "manual" ])
(x: if x == "disable" then 0 else 1)
types.ints.unsigned
);
default = null;
example = 10000;
description = ''
Reduce storage requirements by enabling pruning (deleting) of old
blocks. This allows the pruneblockchain RPC to be called to delete
specific blocks, and enables automatic pruning of old blocks if a
target size in MiB is provided. This mode is incompatible with -txindex
and -rescan. Warning: Reverting this setting requires re-downloading
the entire blockchain. ("disable" = disable pruning blocks, "manual"
= allow manual pruning via RPC, >=550 = automatically prune block files
to stay under the specified target size in MiB)
'';
};
}; };
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
users.users.bitcoin = { environment.systemPackages = [ cfg.package ];
description = "Bitcoind User";
createHome = true;
inherit home;
};
systemd.services.bitcoind = { systemd.services.bitcoind = {
description = "Run bitcoind"; description = "Bitcoin daemon";
path = [ pkgs.bitcoin ]; after = [ "network.target" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
preStart = '' preStart = ''
mkdir -p ${home}/.bitcoin if ! test -e ${cfg.dataDir}; then
ln -sf ${configFile} ${home}/.bitcoin/bitcoin.conf mkdir -m 0770 -p '${cfg.dataDir}'
''; chown '${cfg.user}:${cfg.group}' '${cfg.dataDir}'
ln -s '${configFile}' '${cfg.dataDir}/bitcoin.conf'
fi
'';
serviceConfig = { serviceConfig = {
ExecStart = "${pkgs.bitcoin}/bin/bitcoind"; Type = "simple";
User = "bitcoin"; User = "${cfg.user}";
Group = "${cfg.group}";
ExecStart = "${cfg.package}/bin/bitcoind ${cmdlineOptions}";
StateDirectory = "bitcoind";
PIDFile = "${pidFile}";
Restart = "on-failure"; Restart = "on-failure";
# Hardening measures
PrivateTmp = "true"; PrivateTmp = "true";
ProtectSystem = "full"; ProtectSystem = "full";
NoNewPrivileges = "true"; NoNewPrivileges = "true";
PrivateDevices = "true"; PrivateDevices = "true";
MemoryDenyWriteExecute = "true"; MemoryDenyWriteExecute = "true";
# Permission for preStart
PermissionsStartOnly = "true";
}; };
}; };
users.users.${cfg.user} = {
name = cfg.user;
#uid = config.ids.uids.bitcoin;
group = cfg.group;
description = "Bitcoin daemon user";
home = cfg.dataDir;
};
users.groups.${cfg.group} = {
name = cfg.group;
#gid = config.ids.gids.bitcoin;
};
}; };
} }

View File

@ -29,23 +29,23 @@ in {
services.tor.client.enable = true; services.tor.client.enable = true;
services.tor.hiddenServices.bitcoind = { services.tor.hiddenServices.bitcoind = {
map = [{ map = [{
port = config.services.bitcoin.port; port = config.services.bitcoind.port;
}]; }];
version = 3; version = 3;
}; };
# bitcoin # bitcoind
services.bitcoin.enable = true; services.bitcoind.enable = true;
services.bitcoin.listen = true; services.bitcoind.listen = true;
services.bitcoin.proxy = config.services.tor.client.socksListenAddress; services.bitcoind.proxy = config.services.tor.client.socksListenAddress;
services.bitcoin.port = 8333; services.bitcoind.port = 8333;
services.bitcoin.rpcuser = "bitcoinrpc"; services.bitcoind.rpcuser = "bitcoinrpc";
services.bitcoin.rpcpassword = secrets.bitcoinrpcpassword; services.bitcoind.rpcpassword = secrets.bitcoinrpcpassword;
# clightning # clightning
services.clightning.enable = true; services.clightning.enable = true;
services.clightning.bitcoin-rpcuser = config.services.bitcoin.rpcuser; services.clightning.bitcoin-rpcuser = config.services.bitcoind.rpcuser;
services.clightning.bitcoin-rpcpassword = config.services.bitcoin.rpcpassword; services.clightning.bitcoin-rpcpassword = config.services.bitcoind.rpcpassword;
# nodeinfo # nodeinfo
systemd.services.nodeinfo = { systemd.services.nodeinfo = {

View File

@ -1,6 +1,4 @@
let {
secrets = import ./load-secrets.nix;
in {
network.description = "Bitcoin Core node"; network.description = "Bitcoin Core node";
bitcoin-node = import ./configuration.nix; bitcoin-node = import ./configuration.nix;