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