1{ config, lib, pkgs, ... }:
2
3let
4 cfg = config.services.ergo;
5
6 inherit (lib) mkEnableOption mkIf mkOption optionalString types;
7
8 configFile = pkgs.writeText "ergo.conf" (''
9ergo {
10 directory = "${cfg.dataDir}"
11 node {
12 mining = false
13 }
14 wallet.secretStorage.secretDir = "${cfg.dataDir}/wallet/keystore"
15}
16
17scorex {
18 network {
19 bindAddress = "${cfg.listen.ip}:${toString cfg.listen.port}"
20 }
21'' + optionalString (cfg.api.keyHash != null) ''
22 restApi {
23 apiKeyHash = "${cfg.api.keyHash}"
24 bindAddress = "${cfg.api.listen.ip}:${toString cfg.api.listen.port}"
25 }
26'' + ''
27}
28'');
29
30in {
31
32 options = {
33
34 services.ergo = {
35 enable = mkEnableOption "Ergo service";
36
37 dataDir = mkOption {
38 type = types.path;
39 default = "/var/lib/ergo";
40 description = "The data directory for the Ergo node.";
41 };
42
43 listen = {
44 ip = mkOption {
45 type = types.str;
46 default = "0.0.0.0";
47 description = "IP address on which the Ergo node should listen.";
48 };
49
50 port = mkOption {
51 type = types.port;
52 default = 9006;
53 description = "Listen port for the Ergo node.";
54 };
55 };
56
57 api = {
58 keyHash = mkOption {
59 type = types.nullOr types.str;
60 default = null;
61 example = "324dcf027dd4a30a932c441f365a25e86b173defa4b8e58948253471b81b72cf";
62 description = "Hex-encoded Blake2b256 hash of an API key as a 64-chars long Base16 string.";
63 };
64
65 listen = {
66 ip = mkOption {
67 type = types.str;
68 default = "0.0.0.0";
69 description = "IP address that the Ergo node API should listen on if <option>api.keyHash</option> is defined.";
70 };
71
72 port = mkOption {
73 type = types.port;
74 default = 9052;
75 description = "Listen port for the API endpoint if <option>api.keyHash</option> is defined.";
76 };
77 };
78 };
79
80 testnet = mkOption {
81 type = types.bool;
82 default = false;
83 description = "Connect to testnet network instead of the default mainnet.";
84 };
85
86 user = mkOption {
87 type = types.str;
88 default = "ergo";
89 description = "The user as which to run the Ergo node.";
90 };
91
92 group = mkOption {
93 type = types.str;
94 default = cfg.user;
95 description = "The group as which to run the Ergo node.";
96 };
97
98 openFirewall = mkOption {
99 type = types.bool;
100 default = false;
101 description = "Open ports in the firewall for the Ergo node as well as the API.";
102 };
103 };
104 };
105
106 config = mkIf cfg.enable {
107
108 systemd.tmpfiles.rules = [
109 "d '${cfg.dataDir}' 0770 '${cfg.user}' '${cfg.group}' - -"
110 ];
111
112 systemd.services.ergo = {
113 description = "ergo server";
114 wantedBy = [ "multi-user.target" ];
115 after = [ "network-online.target" ];
116 serviceConfig = {
117 User = cfg.user;
118 Group = cfg.group;
119 ExecStart = ''${pkgs.ergo}/bin/ergo \
120 ${optionalString (!cfg.testnet)
121 "--mainnet"} \
122 -c ${configFile}'';
123 };
124 };
125
126 networking.firewall = mkIf cfg.openFirewall {
127 allowedTCPPorts = [ cfg.listen.port ] ++ [ cfg.api.listen.port ];
128 };
129
130 users.users.${cfg.user} = {
131 name = cfg.user;
132 group = cfg.group;
133 description = "Ergo daemon user";
134 home = cfg.dataDir;
135 isSystemUser = true;
136 };
137
138 users.groups.${cfg.group} = {};
139
140 };
141}