at 25.11-pre 4.0 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.services.cgminer; 9 10 convType = with builtins; v: if lib.isBool v then lib.boolToString v else toString v; 11 mergedHwConfig = lib.mapAttrsToList ( 12 n: v: ''"${n}": "${(lib.concatStringsSep "," (map convType v))}"'' 13 ) (lib.foldAttrs (n: a: [ n ] ++ a) [ ] cfg.hardware); 14 mergedConfig = 15 with builtins; 16 lib.mapAttrsToList ( 17 n: v: ''"${n}": ${if lib.isBool v then convType v else ''"${convType v}"''}'' 18 ) cfg.config; 19 20 cgminerConfig = pkgs.writeText "cgminer.conf" '' 21 { 22 ${lib.concatStringsSep ",\n" mergedHwConfig}, 23 ${lib.concatStringsSep ",\n" mergedConfig}, 24 "pools": [ 25 ${ 26 lib.concatStringsSep ",\n" ( 27 map (v: ''{"url": "${v.url}", "user": "${v.user}", "pass": "${v.pass}"}'') cfg.pools 28 ) 29 }] 30 } 31 ''; 32in 33{ 34 ###### interface 35 options = { 36 37 services.cgminer = { 38 39 enable = lib.mkEnableOption "cgminer, an ASIC/FPGA/GPU miner for bitcoin and litecoin"; 40 41 package = lib.mkPackageOption pkgs "cgminer" { }; 42 43 user = lib.mkOption { 44 type = lib.types.str; 45 default = "cgminer"; 46 description = "User account under which cgminer runs"; 47 }; 48 49 pools = lib.mkOption { 50 default = [ ]; # Run benchmark 51 type = lib.types.listOf (lib.types.attrsOf lib.types.str); 52 description = "List of pools where to mine"; 53 example = [ 54 { 55 url = "http://p2pool.org:9332"; 56 username = "17EUZxTvs9uRmPsjPZSYUU3zCz9iwstudk"; 57 password = "X"; 58 } 59 ]; 60 }; 61 62 hardware = lib.mkOption { 63 default = [ ]; # Run without options 64 type = lib.types.listOf (lib.types.attrsOf (lib.types.either lib.types.str lib.types.int)); 65 description = "List of config options for every GPU"; 66 example = [ 67 { 68 intensity = 9; 69 gpu-engine = "0-985"; 70 gpu-fan = "0-85"; 71 gpu-memclock = 860; 72 gpu-powertune = 20; 73 temp-cutoff = 95; 74 temp-overheat = 85; 75 temp-target = 75; 76 } 77 { 78 intensity = 9; 79 gpu-engine = "0-950"; 80 gpu-fan = "0-85"; 81 gpu-memclock = 825; 82 gpu-powertune = 20; 83 temp-cutoff = 95; 84 temp-overheat = 85; 85 temp-target = 75; 86 } 87 ]; 88 }; 89 90 config = lib.mkOption { 91 default = { }; 92 type = lib.types.attrsOf (lib.types.either lib.types.bool lib.types.int); 93 description = "Additional config"; 94 example = { 95 auto-fan = true; 96 auto-gpu = true; 97 expiry = 120; 98 failover-only = true; 99 gpu-threads = 2; 100 log = 5; 101 queue = 1; 102 scan-time = 60; 103 temp-histeresys = 3; 104 }; 105 }; 106 }; 107 }; 108 109 ###### implementation 110 111 config = lib.mkIf config.services.cgminer.enable { 112 113 users.users = lib.optionalAttrs (cfg.user == "cgminer") { 114 cgminer = { 115 isSystemUser = true; 116 group = "cgminer"; 117 description = "Cgminer user"; 118 }; 119 }; 120 users.groups = lib.optionalAttrs (cfg.user == "cgminer") { 121 cgminer = { }; 122 }; 123 124 environment.systemPackages = [ cfg.package ]; 125 126 systemd.services.cgminer = { 127 path = [ pkgs.cgminer ]; 128 129 after = [ 130 "network.target" 131 "display-manager.service" 132 ]; 133 wantedBy = [ "multi-user.target" ]; 134 135 environment = { 136 LD_LIBRARY_PATH = "/run/opengl-driver/lib:/run/opengl-driver-32/lib"; 137 DISPLAY = ":${toString config.services.xserver.display}"; 138 GPU_MAX_ALLOC_PERCENT = "100"; 139 GPU_USE_SYNC_OBJECTS = "1"; 140 }; 141 142 startLimitIntervalSec = 60; # 1 min 143 serviceConfig = { 144 ExecStart = "${pkgs.cgminer}/bin/cgminer --syslog --text-only --config ${cgminerConfig}"; 145 User = cfg.user; 146 RestartSec = "30s"; 147 Restart = "always"; 148 }; 149 }; 150 151 }; 152 153}