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