1
2{ config, lib, pkgs, ... }:
3
4with lib;
5
6let
7 cfg = config.services.namecoind;
8 dataDir = "/var/lib/namecoind";
9 useSSL = (cfg.rpc.certificate != null) && (cfg.rpc.key != null);
10 useRPC = (cfg.rpc.user != null) && (cfg.rpc.password != null);
11
12 listToConf = option: list:
13 concatMapStrings (value :"${option}=${value}\n") list;
14
15 configFile = pkgs.writeText "namecoin.conf" (''
16 server=1
17 daemon=0
18 txindex=1
19 txprevcache=1
20 walletpath=${cfg.wallet}
21 gen=${if cfg.generate then "1" else "0"}
22 ${listToConf "addnode" cfg.extraNodes}
23 ${listToConf "connect" cfg.trustedNodes}
24 '' + optionalString useRPC ''
25 rpcbind=${cfg.rpc.address}
26 rpcport=${toString cfg.rpc.port}
27 rpcuser=${cfg.rpc.user}
28 rpcpassword=${cfg.rpc.password}
29 ${listToConf "rpcallowip" cfg.rpc.allowFrom}
30 '' + optionalString useSSL ''
31 rpcssl=1
32 rpcsslcertificatechainfile=${cfg.rpc.certificate}
33 rpcsslprivatekeyfile=${cfg.rpc.key}
34 rpcsslciphers=TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH
35 '');
36
37in
38
39{
40
41 ###### interface
42
43 options = {
44
45 services.namecoind = {
46
47 enable = mkEnableOption (lib.mdDoc "namecoind, Namecoin client");
48
49 wallet = mkOption {
50 type = types.path;
51 default = "${dataDir}/wallet.dat";
52 description = lib.mdDoc ''
53 Wallet file. The ownership of the file has to be
54 namecoin:namecoin, and the permissions must be 0640.
55 '';
56 };
57
58 generate = mkOption {
59 type = types.bool;
60 default = false;
61 description = lib.mdDoc ''
62 Whether to generate (mine) Namecoins.
63 '';
64 };
65
66 extraNodes = mkOption {
67 type = types.listOf types.str;
68 default = [ ];
69 description = lib.mdDoc ''
70 List of additional peer IP addresses to connect to.
71 '';
72 };
73
74 trustedNodes = mkOption {
75 type = types.listOf types.str;
76 default = [ ];
77 description = lib.mdDoc ''
78 List of the only peer IP addresses to connect to. If specified
79 no other connection will be made.
80 '';
81 };
82
83 rpc.user = mkOption {
84 type = types.nullOr types.str;
85 default = null;
86 description = lib.mdDoc ''
87 User name for RPC connections.
88 '';
89 };
90
91 rpc.password = mkOption {
92 type = types.nullOr types.str;
93 default = null;
94 description = lib.mdDoc ''
95 Password for RPC connections.
96 '';
97 };
98
99 rpc.address = mkOption {
100 type = types.str;
101 default = "0.0.0.0";
102 description = lib.mdDoc ''
103 IP address the RPC server will bind to.
104 '';
105 };
106
107 rpc.port = mkOption {
108 type = types.port;
109 default = 8332;
110 description = lib.mdDoc ''
111 Port the RPC server will bind to.
112 '';
113 };
114
115 rpc.certificate = mkOption {
116 type = types.nullOr types.path;
117 default = null;
118 example = "/var/lib/namecoind/server.cert";
119 description = lib.mdDoc ''
120 Certificate file for securing RPC connections.
121 '';
122 };
123
124 rpc.key = mkOption {
125 type = types.nullOr types.path;
126 default = null;
127 example = "/var/lib/namecoind/server.pem";
128 description = lib.mdDoc ''
129 Key file for securing RPC connections.
130 '';
131 };
132
133
134 rpc.allowFrom = mkOption {
135 type = types.listOf types.str;
136 default = [ "127.0.0.1" ];
137 description = lib.mdDoc ''
138 List of IP address ranges allowed to use the RPC API.
139 Wiledcards (*) can be user to specify a range.
140 '';
141 };
142
143 };
144
145 };
146
147
148 ###### implementation
149
150 config = mkIf cfg.enable {
151
152 users.users.namecoin = {
153 uid = config.ids.uids.namecoin;
154 description = "Namecoin daemon user";
155 home = dataDir;
156 createHome = true;
157 };
158
159 users.groups.namecoin = {
160 gid = config.ids.gids.namecoin;
161 };
162
163 systemd.services.namecoind = {
164 description = "Namecoind daemon";
165 after = [ "network.target" ];
166 wantedBy = [ "multi-user.target" ];
167
168 startLimitIntervalSec = 120;
169 startLimitBurst = 5;
170 serviceConfig = {
171 User = "namecoin";
172 Group = "namecoin";
173 ExecStart = "${pkgs.namecoind}/bin/namecoind -conf=${configFile} -datadir=${dataDir} -printtoconsole";
174 ExecStop = "${pkgs.coreutils}/bin/kill -KILL $MAINPID";
175 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
176 Nice = "10";
177 PrivateTmp = true;
178 TimeoutStopSec = "60s";
179 TimeoutStartSec = "2s";
180 Restart = "always";
181 };
182
183 preStart = optionalString (cfg.wallet != "${dataDir}/wallet.dat") ''
184 # check wallet file permissions
185 if [ "$(stat --printf '%u' ${cfg.wallet})" != "${toString config.ids.uids.namecoin}" \
186 -o "$(stat --printf '%g' ${cfg.wallet})" != "${toString config.ids.gids.namecoin}" \
187 -o "$(stat --printf '%a' ${cfg.wallet})" != "640" ]; then
188 echo "ERROR: bad ownership or rights on ${cfg.wallet}" >&2
189 exit 1
190 fi
191 '';
192
193 };
194
195 };
196
197 meta.maintainers = with lib.maintainers; [ rnhmjoj ];
198
199}