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