at 23.11-pre 5.9 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.monero; 7 8 listToConf = option: list: 9 concatMapStrings (value: "${option}=${value}\n") list; 10 11 login = (cfg.rpc.user != null && cfg.rpc.password != null); 12 13 configFile = with cfg; pkgs.writeText "monero.conf" '' 14 log-file=/dev/stdout 15 data-dir=${dataDir} 16 17 ${optionalString mining.enable '' 18 start-mining=${mining.address} 19 mining-threads=${toString mining.threads} 20 ''} 21 22 rpc-bind-ip=${rpc.address} 23 rpc-bind-port=${toString rpc.port} 24 ${optionalString login '' 25 rpc-login=${rpc.user}:${rpc.password} 26 ''} 27 ${optionalString rpc.restricted '' 28 restricted-rpc=1 29 ''} 30 31 limit-rate-up=${toString limits.upload} 32 limit-rate-down=${toString limits.download} 33 max-concurrency=${toString limits.threads} 34 block-sync-size=${toString limits.syncSize} 35 36 ${listToConf "add-peer" extraNodes} 37 ${listToConf "add-priority-node" priorityNodes} 38 ${listToConf "add-exclusive-node" exclusiveNodes} 39 40 ${extraConfig} 41 ''; 42 43in 44 45{ 46 47 ###### interface 48 49 options = { 50 51 services.monero = { 52 53 enable = mkEnableOption (lib.mdDoc "Monero node daemon"); 54 55 dataDir = mkOption { 56 type = types.str; 57 default = "/var/lib/monero"; 58 description = lib.mdDoc '' 59 The directory where Monero stores its data files. 60 ''; 61 }; 62 63 mining.enable = mkOption { 64 type = types.bool; 65 default = false; 66 description = lib.mdDoc '' 67 Whether to mine monero. 68 ''; 69 }; 70 71 mining.address = mkOption { 72 type = types.str; 73 default = ""; 74 description = lib.mdDoc '' 75 Monero address where to send mining rewards. 76 ''; 77 }; 78 79 mining.threads = mkOption { 80 type = types.addCheck types.int (x: x>=0); 81 default = 0; 82 description = lib.mdDoc '' 83 Number of threads used for mining. 84 Set to `0` to use all available. 85 ''; 86 }; 87 88 rpc.user = mkOption { 89 type = types.nullOr types.str; 90 default = null; 91 description = lib.mdDoc '' 92 User name for RPC connections. 93 ''; 94 }; 95 96 rpc.password = mkOption { 97 type = types.nullOr types.str; 98 default = null; 99 description = lib.mdDoc '' 100 Password for RPC connections. 101 ''; 102 }; 103 104 rpc.address = mkOption { 105 type = types.str; 106 default = "127.0.0.1"; 107 description = lib.mdDoc '' 108 IP address the RPC server will bind to. 109 ''; 110 }; 111 112 rpc.port = mkOption { 113 type = types.port; 114 default = 18081; 115 description = lib.mdDoc '' 116 Port the RPC server will bind to. 117 ''; 118 }; 119 120 rpc.restricted = mkOption { 121 type = types.bool; 122 default = false; 123 description = lib.mdDoc '' 124 Whether to restrict RPC to view only commands. 125 ''; 126 }; 127 128 limits.upload = mkOption { 129 type = types.addCheck types.int (x: x>=-1); 130 default = -1; 131 description = lib.mdDoc '' 132 Limit of the upload rate in kB/s. 133 Set to `-1` to leave unlimited. 134 ''; 135 }; 136 137 limits.download = mkOption { 138 type = types.addCheck types.int (x: x>=-1); 139 default = -1; 140 description = lib.mdDoc '' 141 Limit of the download rate in kB/s. 142 Set to `-1` to leave unlimited. 143 ''; 144 }; 145 146 limits.threads = mkOption { 147 type = types.addCheck types.int (x: x>=0); 148 default = 0; 149 description = lib.mdDoc '' 150 Maximum number of threads used for a parallel job. 151 Set to `0` to leave unlimited. 152 ''; 153 }; 154 155 limits.syncSize = mkOption { 156 type = types.addCheck types.int (x: x>=0); 157 default = 0; 158 description = lib.mdDoc '' 159 Maximum number of blocks to sync at once. 160 Set to `0` for adaptive. 161 ''; 162 }; 163 164 extraNodes = mkOption { 165 type = types.listOf types.str; 166 default = [ ]; 167 description = lib.mdDoc '' 168 List of additional peer IP addresses to add to the local list. 169 ''; 170 }; 171 172 priorityNodes = mkOption { 173 type = types.listOf types.str; 174 default = [ ]; 175 description = lib.mdDoc '' 176 List of peer IP addresses to connect to and 177 attempt to keep the connection open. 178 ''; 179 }; 180 181 exclusiveNodes = mkOption { 182 type = types.listOf types.str; 183 default = [ ]; 184 description = lib.mdDoc '' 185 List of peer IP addresses to connect to *only*. 186 If given the other peer options will be ignored. 187 ''; 188 }; 189 190 extraConfig = mkOption { 191 type = types.lines; 192 default = ""; 193 description = lib.mdDoc '' 194 Extra lines to be added verbatim to monerod configuration. 195 ''; 196 }; 197 198 }; 199 200 }; 201 202 203 ###### implementation 204 205 config = mkIf cfg.enable { 206 207 users.users.monero = { 208 isSystemUser = true; 209 group = "monero"; 210 description = "Monero daemon user"; 211 home = cfg.dataDir; 212 createHome = true; 213 }; 214 215 users.groups.monero = { }; 216 217 systemd.services.monero = { 218 description = "monero daemon"; 219 after = [ "network.target" ]; 220 wantedBy = [ "multi-user.target" ]; 221 222 serviceConfig = { 223 User = "monero"; 224 Group = "monero"; 225 ExecStart = "${pkgs.monero-cli}/bin/monerod --config-file=${configFile} --non-interactive"; 226 Restart = "always"; 227 SuccessExitStatus = [ 0 1 ]; 228 }; 229 }; 230 231 assertions = singleton { 232 assertion = cfg.mining.enable -> cfg.mining.address != ""; 233 message = '' 234 You need a Monero address to receive mining rewards: 235 specify one using option monero.mining.address. 236 ''; 237 }; 238 239 }; 240 241 meta.maintainers = with lib.maintainers; [ rnhmjoj ]; 242 243} 244