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