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