1 { config, lib, pkgs, ... }:
4 eachBlockbook = config.services.blockbook-frontend;
6 blockbookOpts = { config, lib, name, ...}: {
10 enable = lib.mkEnableOption "blockbook-frontend application";
12 package = lib.mkPackageOption pkgs "blockbook" { };
16 default = "blockbook-frontend-${name}";
17 description = "The user as which to run blockbook-frontend-${name}.";
20 group = lib.mkOption {
22 default = "${config.user}";
23 description = "The group as which to run blockbook-frontend-${name}.";
26 certFile = lib.mkOption {
27 type = lib.types.nullOr lib.types.path;
29 example = "/etc/secrets/blockbook-frontend-${name}/certFile";
31 To enable SSL, specify path to the name of certificate files without extension.
32 Expecting {file}`certFile.crt` and {file}`certFile.key`.
36 configFile = lib.mkOption {
37 type = with lib.types; nullOr path;
39 example = "${config.dataDir}/config.json";
40 description = "Location of the blockbook configuration file.";
43 coinName = lib.mkOption {
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).
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/"'';
58 Location of the dir with {file}`main.css` CSS file.
59 By default, the one shipped with the package is used.
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.";
69 debug = lib.mkOption {
70 type = lib.types.bool;
72 description = "Debug mode, return more verbose errors, reload templates on each request.";
75 internal = lib.mkOption {
76 type = lib.types.nullOr lib.types.str;
78 description = "Internal http server binding `[address]:port`.";
81 messageQueueBinding = lib.mkOption {
83 default = "tcp://127.0.0.1:38330";
84 description = "Message Queue Binding `address:port`.";
87 public = lib.mkOption {
88 type = lib.types.nullOr lib.types.str;
90 description = "Public http server binding `[address]:port`.";
96 default = "http://127.0.0.1";
97 description = "URL for JSON-RPC connections.";
100 port = lib.mkOption {
101 type = lib.types.port;
103 description = "Port for JSON-RPC connections.";
106 user = lib.mkOption {
107 type = lib.types.str;
109 description = "Username for JSON-RPC connections.";
112 password = lib.mkOption {
113 type = lib.types.str;
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.
122 passwordFile = lib.mkOption {
123 type = lib.types.nullOr lib.types.path;
126 File containing password of the RPC user.
127 Note: This options is ignored when `configFile` is used.
132 sync = lib.mkOption {
133 type = lib.types.bool;
135 description = "Synchronizes until tip, if together with zeromq, keeps index synchronized.";
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.";
146 extraConfig = lib.mkOption {
147 type = lib.types.attrs;
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";
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;
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).
174 extraCmdLineOptions = lib.mkOption {
175 type = lib.types.listOf lib.types.str;
177 example = [ "-workers=1" "-dbcache=0" "-logtosderr" ];
179 Extra command line options to pass to Blockbook.
180 Run blockbook --help to list all available options.
190 services.blockbook-frontend = lib.mkOption {
191 type = lib.types.attrsOf (lib.types.submodule blockbookOpts);
193 description = "Specification of one or more blockbook-frontend instances.";
199 config = lib.mkIf (eachBlockbook != {}) {
201 systemd.services = lib.mapAttrs' (blockbookName: cfg: (
202 lib.nameValuePair "blockbook-frontend-${blockbookName}" (
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)
214 description = "blockbook-frontend-${blockbookName} daemon";
215 after = [ "network.target" ];
216 wantedBy = [ "multi-user.target" ];
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) ''
222 ${pkgs.jq}/bin/jq ".rpc_pass = \"$(cat ${cfg.rpc.passwordFile})\"" ${configFile} > $CONFIGTMP
223 mv $CONFIGTMP ${cfg.dataDir}/${blockbookName}-config.json
230 ${cfg.package}/bin/blockbook \
231 ${if (cfg.rpc.passwordFile != null && cfg.configFile == null) then
232 "-blockchaincfg=${cfg.dataDir}/${blockbookName}-config.json"
234 "-blockchaincfg=${configFile}"
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}
244 Restart = "on-failure";
245 WorkingDirectory = cfg.dataDir;
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} - -"
256 users.users = lib.mapAttrs' (blockbookName: cfg: (
257 lib.nameValuePair "blockbook-frontend-${blockbookName}" {
264 users.groups = lib.mapAttrs' (instanceName: cfg: (
265 lib.nameValuePair "${cfg.group}" { })) eachBlockbook;
268 meta.maintainers = with lib.maintainers; [ _1000101 ];