1/* 2 3This file is for options that NixOS and nix-darwin have in common. 4 5Platform-specific code is in the respective default.nix files. 6 7 */ 8 9{ config, lib, options, pkgs, ... }: 10let 11 inherit (lib) 12 filterAttrs 13 literalExample 14 mkIf 15 mkOption 16 mkRemovedOptionModule 17 mkRenamedOptionModule 18 types 19 ; 20 21 cfg = 22 config.services.hercules-ci-agent; 23 24 format = pkgs.formats.toml { }; 25 26 settingsModule = { config, ... }: { 27 freeformType = format.type; 28 options = { 29 baseDirectory = mkOption { 30 type = types.path; 31 default = "/var/lib/hercules-ci-agent"; 32 description = '' 33 State directory (secrets, work directory, etc) for agent 34 ''; 35 }; 36 concurrentTasks = mkOption { 37 description = '' 38 Number of tasks to perform simultaneously. 39 40 A task is a single derivation build, an evaluation or an effect run. 41 At minimum, you need 2 concurrent tasks for <literal>x86_64-linux</literal> 42 in your cluster, to allow for import from derivation. 43 44 <literal>concurrentTasks</literal> can be around the CPU core count or lower if memory is 45 the bottleneck. 46 47 The optimal value depends on the resource consumption characteristics of your workload, 48 including memory usage and in-task parallelism. This is typically determined empirically. 49 50 When scaling, it is generally better to have a double-size machine than two machines, 51 because each split of resources causes inefficiencies; particularly with regards 52 to build latency because of extra downloads. 53 ''; 54 type = types.either types.ints.positive (types.enum [ "auto" ]); 55 default = "auto"; 56 }; 57 workDirectory = mkOption { 58 description = '' 59 The directory in which temporary subdirectories are created for task state. This includes sources for Nix evaluation. 60 ''; 61 type = types.path; 62 default = config.baseDirectory + "/work"; 63 defaultText = literalExample ''baseDirectory + "/work"''; 64 }; 65 staticSecretsDirectory = mkOption { 66 description = '' 67 This is the default directory to look for statically configured secrets like <literal>cluster-join-token.key</literal>. 68 ''; 69 type = types.path; 70 default = config.baseDirectory + "/secrets"; 71 defaultText = literalExample ''baseDirectory + "/secrets"''; 72 }; 73 clusterJoinTokenPath = mkOption { 74 description = '' 75 Location of the cluster-join-token.key file. 76 ''; 77 type = types.path; 78 default = config.staticSecretsDirectory + "/cluster-join-token.key"; 79 defaultText = literalExample ''staticSecretsDirectory + "/cluster-join-token.key"''; 80 # internal: It's a bit too detailed to show by default in the docs, 81 # but useful to define explicitly to allow reuse by other modules. 82 internal = true; 83 }; 84 binaryCachesPath = mkOption { 85 description = '' 86 Location of the binary-caches.json file. 87 ''; 88 type = types.path; 89 default = config.staticSecretsDirectory + "/binary-caches.json"; 90 defaultText = literalExample ''staticSecretsDirectory + "/binary-caches.json"''; 91 # internal: It's a bit too detailed to show by default in the docs, 92 # but useful to define explicitly to allow reuse by other modules. 93 internal = true; 94 }; 95 }; 96 }; 97 98 # TODO (roberth, >=2022) remove 99 checkNix = 100 if !cfg.checkNix 101 then "" 102 else if lib.versionAtLeast config.nix.package.version "2.3.10" 103 then "" 104 else 105 pkgs.stdenv.mkDerivation { 106 name = "hercules-ci-check-system-nix-src"; 107 inherit (config.nix.package) src patches; 108 configurePhase = ":"; 109 buildPhase = '' 110 echo "Checking in-memory pathInfoCache expiry" 111 if ! grep 'PathInfoCacheValue' src/libstore/store-api.hh >/dev/null; then 112 cat 1>&2 <<EOF 113 114 You are deploying Hercules CI Agent on a system with an incompatible 115 nix-daemon. Please make sure nix.package is set to a Nix version of at 116 least 2.3.10 or a master version more recent than Mar 12, 2020. 117 EOF 118 exit 1 119 fi 120 ''; 121 installPhase = "touch $out"; 122 }; 123 124in 125{ 126 imports = [ 127 (mkRenamedOptionModule [ "services" "hercules-ci-agent" "extraOptions" ] [ "services" "hercules-ci-agent" "settings" ]) 128 (mkRenamedOptionModule [ "services" "hercules-ci-agent" "baseDirectory" ] [ "services" "hercules-ci-agent" "settings" "baseDirectory" ]) 129 (mkRenamedOptionModule [ "services" "hercules-ci-agent" "concurrentTasks" ] [ "services" "hercules-ci-agent" "settings" "concurrentTasks" ]) 130 (mkRemovedOptionModule [ "services" "hercules-ci-agent" "patchNix" ] "Nix versions packaged in this version of Nixpkgs don't need a patched nix-daemon to work correctly in Hercules CI Agent clusters.") 131 ]; 132 133 options.services.hercules-ci-agent = { 134 enable = mkOption { 135 type = types.bool; 136 default = false; 137 description = '' 138 Enable to run Hercules CI Agent as a system service. 139 140 <link xlink:href="https://hercules-ci.com">Hercules CI</link> is a 141 continuous integation service that is centered around Nix. 142 143 Support is available at <link xlink:href="mailto:help@hercules-ci.com">help@hercules-ci.com</link>. 144 ''; 145 }; 146 checkNix = mkOption { 147 type = types.bool; 148 default = true; 149 description = '' 150 Whether to make sure that the system's Nix (nix-daemon) is compatible. 151 152 If you set this to false, please keep up with the change log. 153 ''; 154 }; 155 package = mkOption { 156 description = '' 157 Package containing the bin/hercules-ci-agent executable. 158 ''; 159 type = types.package; 160 default = pkgs.hercules-ci-agent; 161 defaultText = literalExample "pkgs.hercules-ci-agent"; 162 }; 163 settings = mkOption { 164 description = '' 165 These settings are written to the <literal>agent.toml</literal> file. 166 167 Not all settings are listed as options, can be set nonetheless. 168 169 For the exhaustive list of settings, see <link xlink:href="https://docs.hercules-ci.com/hercules-ci/reference/agent-config/"/>. 170 ''; 171 type = types.submoduleWith { modules = [ settingsModule ]; }; 172 }; 173 174 /* 175 Internal and/or computed values. 176 177 These are written as options instead of let binding to allow sharing with 178 default.nix on both NixOS and nix-darwin. 179 */ 180 tomlFile = mkOption { 181 type = types.path; 182 internal = true; 183 defaultText = "generated hercules-ci-agent.toml"; 184 description = '' 185 The fully assembled config file. 186 ''; 187 }; 188 }; 189 190 config = mkIf cfg.enable { 191 nix.extraOptions = lib.addContextFrom checkNix '' 192 # A store path that was missing at first may well have finished building, 193 # even shortly after the previous lookup. This *also* applies to the daemon. 194 narinfo-cache-negative-ttl = 0 195 ''; 196 services.hercules-ci-agent = { 197 tomlFile = 198 format.generate "hercules-ci-agent.toml" cfg.settings; 199 200 settings.labels = { 201 agent.source = 202 if options.services.hercules-ci-agent.package.highestPrio == (lib.modules.mkOptionDefault { }).priority 203 then "nixpkgs" 204 else lib.mkOptionDefault "override"; 205 pkgs.version = pkgs.lib.version; 206 lib.version = lib.version; 207 }; 208 }; 209 }; 210}