Merge: zmap: 4.2.0 -> 4.3.1 (#364578)
[NixPkgs.git] / nixos / modules / services / networking / blockbook-frontend.nix
blobbc9a3633fc69c42e75f0eab0e48230bd3d092418
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
7 let
9   eachBlockbook = config.services.blockbook-frontend;
11   blockbookOpts =
12     {
13       config,
14       lib,
15       name,
16       ...
17     }:
18     {
20       options = {
22         enable = lib.mkEnableOption "blockbook-frontend application";
24         package = lib.mkPackageOption pkgs "blockbook" { };
26         user = lib.mkOption {
27           type = lib.types.str;
28           default = "blockbook-frontend-${name}";
29           description = "The user as which to run blockbook-frontend-${name}.";
30         };
32         group = lib.mkOption {
33           type = lib.types.str;
34           default = "${config.user}";
35           description = "The group as which to run blockbook-frontend-${name}.";
36         };
38         certFile = lib.mkOption {
39           type = lib.types.nullOr lib.types.path;
40           default = null;
41           example = "/etc/secrets/blockbook-frontend-${name}/certFile";
42           description = ''
43             To enable SSL, specify path to the name of certificate files without extension.
44             Expecting {file}`certFile.crt` and {file}`certFile.key`.
45           '';
46         };
48         configFile = lib.mkOption {
49           type = with lib.types; nullOr path;
50           default = null;
51           example = "${config.dataDir}/config.json";
52           description = "Location of the blockbook configuration file.";
53         };
55         coinName = lib.mkOption {
56           type = lib.types.str;
57           default = "Bitcoin";
58           description = ''
59             See <https://github.com/trezor/blockbook/blob/master/bchain/coins/blockchain.go#L61>
60             for current of coins supported in master (Note: may differ from release).
61           '';
62         };
64         cssDir = lib.mkOption {
65           type = lib.types.path;
66           default = "${config.package}/share/css/";
67           defaultText = lib.literalExpression ''"''${package}/share/css/"'';
68           example = lib.literalExpression ''"''${dataDir}/static/css/"'';
69           description = ''
70             Location of the dir with {file}`main.css` CSS file.
71             By default, the one shipped with the package is used.
72           '';
73         };
75         dataDir = lib.mkOption {
76           type = lib.types.path;
77           default = "/var/lib/blockbook-frontend-${name}";
78           description = "Location of blockbook-frontend-${name} data directory.";
79         };
81         debug = lib.mkOption {
82           type = lib.types.bool;
83           default = false;
84           description = "Debug mode, return more verbose errors, reload templates on each request.";
85         };
87         internal = lib.mkOption {
88           type = lib.types.nullOr lib.types.str;
89           default = ":9030";
90           description = "Internal http server binding `[address]:port`.";
91         };
93         messageQueueBinding = lib.mkOption {
94           type = lib.types.str;
95           default = "tcp://127.0.0.1:38330";
96           description = "Message Queue Binding `address:port`.";
97         };
99         public = lib.mkOption {
100           type = lib.types.nullOr lib.types.str;
101           default = ":9130";
102           description = "Public http server binding `[address]:port`.";
103         };
105         rpc = {
106           url = lib.mkOption {
107             type = lib.types.str;
108             default = "http://127.0.0.1";
109             description = "URL for JSON-RPC connections.";
110           };
112           port = lib.mkOption {
113             type = lib.types.port;
114             default = 8030;
115             description = "Port for JSON-RPC connections.";
116           };
118           user = lib.mkOption {
119             type = lib.types.str;
120             default = "rpc";
121             description = "Username for JSON-RPC connections.";
122           };
124           password = lib.mkOption {
125             type = lib.types.str;
126             default = "rpc";
127             description = ''
128               RPC password for JSON-RPC connections.
129               Warning: this is stored in cleartext in the Nix store!!!
130               Use `configFile` or `passwordFile` if needed.
131             '';
132           };
134           passwordFile = lib.mkOption {
135             type = lib.types.nullOr lib.types.path;
136             default = null;
137             description = ''
138               File containing password of the RPC user.
139               Note: This options is ignored when `configFile` is used.
140             '';
141           };
142         };
144         sync = lib.mkOption {
145           type = lib.types.bool;
146           default = true;
147           description = "Synchronizes until tip, if together with zeromq, keeps index synchronized.";
148         };
150         templateDir = lib.mkOption {
151           type = lib.types.path;
152           default = "${config.package}/share/templates/";
153           defaultText = lib.literalExpression ''"''${package}/share/templates/"'';
154           example = lib.literalExpression ''"''${dataDir}/templates/static/"'';
155           description = "Location of the HTML templates. By default, ones shipped with the package are used.";
156         };
158         extraConfig = lib.mkOption {
159           type = lib.types.attrs;
160           default = { };
161           example = lib.literalExpression ''
162             {
163                      "alternative_estimate_fee" = "whatthefee-disabled";
164                      "alternative_estimate_fee_params" = "{\"url\": \"https://whatthefee.io/data.json\", \"periodSeconds\": 60}";
165                      "fiat_rates" = "coingecko";
166                      "fiat_rates_params" = "{\"url\": \"https://api.coingecko.com/api/v3\", \"coin\": \"bitcoin\", \"periodSeconds\": 60}";
167                      "coin_shortcut" = "BTC";
168                      "coin_label" = "Bitcoin";
169                      "parse" = true;
170                      "subversion" = "";
171                      "address_format" = "";
172                      "xpub_magic" = 76067358;
173                      "xpub_magic_segwit_p2sh" = 77429938;
174                      "xpub_magic_segwit_native" = 78792518;
175                      "mempool_workers" = 8;
176                      "mempool_sub_workers" = 2;
177                      "block_addresses_to_keep" = 300;
178                    }'';
179           description = ''
180             Additional configurations to be appended to {file}`coin.conf`.
181             Overrides any already defined configuration options.
182             See <https://github.com/trezor/blockbook/tree/master/configs/coins>
183             for current configuration options supported in master (Note: may differ from release).
184           '';
185         };
187         extraCmdLineOptions = lib.mkOption {
188           type = lib.types.listOf lib.types.str;
189           default = [ ];
190           example = [
191             "-workers=1"
192             "-dbcache=0"
193             "-logtosderr"
194           ];
195           description = ''
196             Extra command line options to pass to Blockbook.
197             Run blockbook --help to list all available options.
198           '';
199         };
200       };
201     };
204   # interface
206   options = {
207     services.blockbook-frontend = lib.mkOption {
208       type = lib.types.attrsOf (lib.types.submodule blockbookOpts);
209       default = { };
210       description = "Specification of one or more blockbook-frontend instances.";
211     };
212   };
214   # implementation
216   config = lib.mkIf (eachBlockbook != { }) {
218     systemd.services = lib.mapAttrs' (
219       blockbookName: cfg:
220       (lib.nameValuePair "blockbook-frontend-${blockbookName}" (
221         let
222           configFile =
223             if cfg.configFile != null then
224               cfg.configFile
225             else
226               pkgs.writeText "config.conf" (
227                 builtins.toJSON (
228                   {
229                     coin_name = "${cfg.coinName}";
230                     rpc_user = "${cfg.rpc.user}";
231                     rpc_pass = "${cfg.rpc.password}";
232                     rpc_url = "${cfg.rpc.url}:${toString cfg.rpc.port}";
233                     message_queue_binding = "${cfg.messageQueueBinding}";
234                   }
235                   // cfg.extraConfig
236                 )
237               );
238         in
239         {
240           description = "blockbook-frontend-${blockbookName} daemon";
241           after = [ "network.target" ];
242           wantedBy = [ "multi-user.target" ];
243           preStart = ''
244             ln -sf ${cfg.templateDir} ${cfg.dataDir}/static/
245             ln -sf ${cfg.cssDir} ${cfg.dataDir}/static/
246             ${lib.optionalString (cfg.rpc.passwordFile != null && cfg.configFile == null) ''
247               CONFIGTMP=$(mktemp)
248               ${pkgs.jq}/bin/jq ".rpc_pass = \"$(cat ${cfg.rpc.passwordFile})\"" ${configFile} > $CONFIGTMP
249               mv $CONFIGTMP ${cfg.dataDir}/${blockbookName}-config.json
250             ''}
251           '';
252           serviceConfig = {
253             User = cfg.user;
254             Group = cfg.group;
255             ExecStart = ''
256               ${cfg.package}/bin/blockbook \
257               ${
258                 if (cfg.rpc.passwordFile != null && cfg.configFile == null) then
259                   "-blockchaincfg=${cfg.dataDir}/${blockbookName}-config.json"
260                 else
261                   "-blockchaincfg=${configFile}"
262               } \
263               -datadir=${cfg.dataDir} \
264               ${lib.optionalString (cfg.sync != false) "-sync"} \
265               ${lib.optionalString (cfg.certFile != null) "-certfile=${toString cfg.certFile}"} \
266               ${lib.optionalString (cfg.debug != false) "-debug"} \
267               ${lib.optionalString (cfg.internal != null) "-internal=${toString cfg.internal}"} \
268               ${lib.optionalString (cfg.public != null) "-public=${toString cfg.public}"} \
269               ${toString cfg.extraCmdLineOptions}
270             '';
271             Restart = "on-failure";
272             WorkingDirectory = cfg.dataDir;
273             LimitNOFILE = 65536;
274           };
275         }
276       ))
277     ) eachBlockbook;
279     systemd.tmpfiles.rules = lib.flatten (
280       lib.mapAttrsToList (blockbookName: cfg: [
281         "d ${cfg.dataDir} 0750 ${cfg.user} ${cfg.group} - -"
282         "d ${cfg.dataDir}/static 0750 ${cfg.user} ${cfg.group} - -"
283       ]) eachBlockbook
284     );
286     users.users = lib.mapAttrs' (
287       blockbookName: cfg:
288       (lib.nameValuePair "blockbook-frontend-${blockbookName}" {
289         name = cfg.user;
290         group = cfg.group;
291         home = cfg.dataDir;
292         isSystemUser = true;
293       })
294     ) eachBlockbook;
296     users.groups = lib.mapAttrs' (
297       instanceName: cfg: (lib.nameValuePair "${cfg.group}" { })
298     ) eachBlockbook;
299   };
301   meta.maintainers = with lib.maintainers; [ _1000101 ];