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 (if v then "true" else "false") 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 = mkOption { 35 default = false; 36 description = '' 37 Whether to enable cgminer, an ASIC/FPGA/GPU miner for bitcoin and 38 litecoin. 39 ''; 40 }; 41 42 package = mkOption { 43 default = pkgs.cgminer; 44 defaultText = "pkgs.cgminer"; 45 description = "Which cgminer derivation to use."; 46 type = types.package; 47 }; 48 49 user = mkOption { 50 default = "cgminer"; 51 description = "User account under which cgminer runs"; 52 }; 53 54 pools = mkOption { 55 default = []; # Run benchmark 56 description = "List of pools where to mine"; 57 example = [{ 58 url = "http://p2pool.org:9332"; 59 username = "17EUZxTvs9uRmPsjPZSYUU3zCz9iwstudk"; 60 password="X"; 61 }]; 62 }; 63 64 hardware = mkOption { 65 default = []; # Run without options 66 description= "List of config options for every GPU"; 67 example = [ 68 { 69 intensity = 9; 70 gpu-engine = "0-985"; 71 gpu-fan = "0-85"; 72 gpu-memclock = 860; 73 gpu-powertune = 20; 74 temp-cutoff = 95; 75 temp-overheat = 85; 76 temp-target = 75; 77 } 78 { 79 intensity = 9; 80 gpu-engine = "0-950"; 81 gpu-fan = "0-85"; 82 gpu-memclock = 825; 83 gpu-powertune = 20; 84 temp-cutoff = 95; 85 temp-overheat = 85; 86 temp-target = 75; 87 }]; 88 }; 89 90 config = mkOption { 91 default = {}; 92 description = "Additional config"; 93 example = { 94 auto-fan = true; 95 auto-gpu = true; 96 expiry = 120; 97 failover-only = true; 98 gpu-threads = 2; 99 log = 5; 100 queue = 1; 101 scan-time = 60; 102 temp-histeresys = 3; 103 }; 104 }; 105 }; 106 }; 107 108 109 ###### implementation 110 111 config = mkIf config.services.cgminer.enable { 112 113 users.extraUsers = optionalAttrs (cfg.user == "cgminer") (singleton 114 { name = "cgminer"; 115 uid = config.ids.uids.cgminer; 116 description = "Cgminer user"; 117 }); 118 119 environment.systemPackages = [ cfg.package ]; 120 121 systemd.services.cgminer = { 122 path = [ pkgs.cgminer ]; 123 124 after = [ "network.target" "display-manager.service" ]; 125 wantedBy = [ "multi-user.target" ]; 126 127 environment = { 128 LD_LIBRARY_PATH = ''/run/opengl-driver/lib:/run/opengl-driver-32/lib''; 129 DISPLAY = ":0"; 130 GPU_MAX_ALLOC_PERCENT = "100"; 131 GPU_USE_SYNC_OBJECTS = "1"; 132 }; 133 134 serviceConfig = { 135 ExecStart = "${pkgs.cgminer}/bin/cgminer --syslog --text-only --config ${cgminerConfig}"; 136 User = cfg.user; 137 RestartSec = "30s"; 138 Restart = "always"; 139 StartLimitInterval = "1m"; 140 }; 141 }; 142 143 }; 144 145}