-
Notifications
You must be signed in to change notification settings - Fork 106
/
fulcrum.nix
140 lines (124 loc) · 3.98 KB
/
fulcrum.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
{ config, lib, pkgs, ... }:
with lib;
let
options.services.fulcrum = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Enable fulcrum, an Electrum server implemented in C++.
Compared to electrs, fulcrum has a 3x larger database size but
can serve arbitrary address queries instantly.
fulcrum also enables `txindex` in bitcoind (this is a requirement),
which increases the bitcoind datadir size by 8% of the `blocks` size.
This module disables peering (a distributed list of electrum servers that can
be queried by clients), but you can manually enable it via option
{option}`extraConfig`.
'';
};
address = mkOption {
type = types.str;
default = "127.0.0.1";
description = "Address to listen for RPC connections.";
};
port = mkOption {
type = types.port;
default = 50001;
description = "Port to listen for RPC connections.";
};
dataDir = mkOption {
type = types.path;
default = "/var/lib/fulcrum";
description = "The data directory for fulcrum.";
};
extraConfig = mkOption {
type = types.lines;
default = "";
example = ''
peering = true
'';
description = ''
Extra lines appended to the configuration file.
See all available options at
https://github.com/cculianu/Fulcrum/blob/master/doc/fulcrum-example-config.conf
'';
};
user = mkOption {
type = types.str;
default = "fulcrum";
description = "The user as which to run fulcrum.";
};
group = mkOption {
type = types.str;
default = cfg.user;
description = "The group as which to run fulcrum.";
};
tor.enforce = nbLib.tor.enforce;
};
cfg = config.services.fulcrum;
nbLib = config.nix-bitcoin.lib;
secretsDir = config.nix-bitcoin.secretsDir;
bitcoind = config.services.bitcoind;
configFile = builtins.toFile "fulcrum.conf" ''
datadir = ${cfg.dataDir}
tcp = ${cfg.address}:${toString cfg.port}
bitcoind = ${nbLib.addressWithPort bitcoind.rpc.address bitcoind.rpc.port}
rpcuser = ${bitcoind.rpc.users.public.name}
# Disable logging timestamps
ts-format = none
peering = false
${cfg.extraConfig}
'';
in {
inherit options;
config = mkIf cfg.enable {
assertions = [
{ assertion = bitcoind.prune == 0;
message = "Fulcrum does not support bitcoind pruning.";
}
{ assertion =
!(config.services ? electrs)
|| !config.services.electrs.enable
|| config.services.electrs.port != cfg.port;
message = ''
Fulcrum and Electrs can't both bind to TCP RPC port ${cfg.port}.
Change `services.electrs.port` or `services.fulcrum.port`
to a port other than ${cfg.port}.
'';
}
];
services.bitcoind = {
enable = true;
txindex = true;
};
systemd.tmpfiles.rules = [
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
];
systemd.services.fulcrum = {
wantedBy = [ "multi-user.target" ];
requires = [ "bitcoind.service" ];
after = [ "bitcoind.service" "nix-bitcoin-secrets.target" ];
preStart = ''
{
cat ${configFile}
echo "rpcpassword = $(cat ${secretsDir}/bitcoin-rpcpassword-public)"
} > '${cfg.dataDir}/fulcrum.conf'
'';
serviceConfig = nbLib.defaultHardening // {
ExecStart = "${config.nix-bitcoin.pkgs.fulcrum}/bin/Fulcrum '${cfg.dataDir}/fulcrum.conf'";
User = cfg.user;
Group = cfg.group;
Restart = "on-failure";
RestartSec = "10s";
ReadWritePaths = cfg.dataDir;
ProcSubset = "all"; # Fulcrum requires read access to /proc/meminfo
} // nbLib.allowedIPAddresses cfg.tor.enforce;
};
users.users.${cfg.user} = {
isSystemUser = true;
group = cfg.group;
extraGroups = [ "bitcoinrpc-public" ];
};
users.groups.${cfg.group} = {};
};
}