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,29 +1,147 @@
{ 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 {
services.bitcoind = {
enable = mkEnableOption "Bitcoin daemon";
package = mkOption {
type = types.package;
default = pkgs.altcoins.bitcoind;
defaultText = "pkgs.altcoins.bitcoind";
description = "The package providing bitcoin binaries.";
};
extraConfig = mkOption {
type = types.lines;
default = "";
example = ''
par=16
rpcthreads=16
logips=1
assumevalid=0000000000000000000726d186d6298b5054b9a5c49639752294b322a305d240
addnode=ecoc5q34tmbq54wl.onion
discover=0
printtoconsole=1
'';
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; type = types.bool;
default = false; default = false;
description = '' description = "Whether to use the test chain.";
If enabled, the bitcoin service will be installed. };
''; port = mkOption {
type = types.nullOr types.ints.u16;
default = null;
description = "Override the default port on which to listen for connections.";
};
proxy = mkOption {
type = types.nullOr types.string;
default = null;
description = "Connect through SOCKS5 proxy";
}; };
listen = mkOption { listen = mkOption {
type = types.bool; type = types.bool;
@ -32,54 +150,77 @@ in {
If enabled, the bitcoin service will listen. If enabled, the bitcoin service will listen.
''; '';
}; };
proxy = mkOption { dbCache = mkOption {
type = types.nullOr types.string; type = types.nullOr (types.ints.between 4 16384);
default = null; default = null;
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 = '' description = ''
proxy 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)
''; '';
}; };
port = mkOption {
type = types.nullOr types.ints.u16;
default = null;
description = "Override the default port on which to listen for connections.";
};
rpcuser = mkOption {
type = types.nullOr types.string;
default = null;
description = "Set bitcoin RPC user";
};
rpcpassword = mkOption {
type = types.nullOr types.string;
default = null;
description = "Set bitcoin RPC password";
}; };
}; };
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;