at 23.05-pre 5.5 kB view raw
1{ config, lib, pkgs, ... }: 2with lib; 3let 4 cfg = config.services.nomad; 5 format = pkgs.formats.json { }; 6in 7{ 8 ##### interface 9 options = { 10 services.nomad = { 11 enable = mkEnableOption (lib.mdDoc "Nomad, a distributed, highly available, datacenter-aware scheduler"); 12 13 package = mkOption { 14 type = types.package; 15 default = pkgs.nomad; 16 defaultText = literalExpression "pkgs.nomad"; 17 description = lib.mdDoc '' 18 The package used for the Nomad agent and CLI. 19 ''; 20 }; 21 22 extraPackages = mkOption { 23 type = types.listOf types.package; 24 default = [ ]; 25 description = lib.mdDoc '' 26 Extra packages to add to {env}`PATH` for the Nomad agent process. 27 ''; 28 example = literalExpression '' 29 with pkgs; [ cni-plugins ] 30 ''; 31 }; 32 33 dropPrivileges = mkOption { 34 type = types.bool; 35 default = true; 36 description = lib.mdDoc '' 37 Whether the nomad agent should be run as a non-root nomad user. 38 ''; 39 }; 40 41 enableDocker = mkOption { 42 type = types.bool; 43 default = true; 44 description = lib.mdDoc '' 45 Enable Docker support. Needed for Nomad's docker driver. 46 47 Note that the docker group membership is effectively equivalent 48 to being root, see https://github.com/moby/moby/issues/9976. 49 ''; 50 }; 51 52 extraSettingsPaths = mkOption { 53 type = types.listOf types.path; 54 default = [ ]; 55 description = lib.mdDoc '' 56 Additional settings paths used to configure nomad. These can be files or directories. 57 ''; 58 example = literalExpression '' 59 [ "/etc/nomad-mutable.json" "/run/keys/nomad-with-secrets.json" "/etc/nomad/config.d" ] 60 ''; 61 }; 62 63 extraSettingsPlugins = mkOption { 64 type = types.listOf (types.either types.package types.path); 65 default = [ ]; 66 description = lib.mdDoc '' 67 Additional plugins dir used to configure nomad. 68 ''; 69 example = literalExpression '' 70 [ "<pluginDir>" "pkgs.<plugins-name>"] 71 ''; 72 }; 73 74 75 settings = mkOption { 76 type = format.type; 77 default = { }; 78 description = lib.mdDoc '' 79 Configuration for Nomad. See the [documentation](https://www.nomadproject.io/docs/configuration) 80 for supported values. 81 82 Notes about `data_dir`: 83 84 If `data_dir` is set to a value other than the 85 default value of `"/var/lib/nomad"` it is the Nomad 86 cluster manager's responsibility to make sure that this directory 87 exists and has the appropriate permissions. 88 89 Additionally, if `dropPrivileges` is 90 `true` then `data_dir` 91 *cannot* be customized. Setting 92 `dropPrivileges` to `true` enables 93 the `DynamicUser` feature of systemd which directly 94 manages and operates on `StateDirectory`. 95 ''; 96 example = literalExpression '' 97 { 98 # A minimal config example: 99 server = { 100 enabled = true; 101 bootstrap_expect = 1; # for demo; no fault tolerance 102 }; 103 client = { 104 enabled = true; 105 }; 106 } 107 ''; 108 }; 109 }; 110 }; 111 112 ##### implementation 113 config = mkIf cfg.enable { 114 services.nomad.settings = { 115 # Agrees with `StateDirectory = "nomad"` set below. 116 data_dir = mkDefault "/var/lib/nomad"; 117 }; 118 119 environment = { 120 etc."nomad.json".source = format.generate "nomad.json" cfg.settings; 121 systemPackages = [ cfg.package ]; 122 }; 123 124 systemd.services.nomad = { 125 description = "Nomad"; 126 wantedBy = [ "multi-user.target" ]; 127 wants = [ "network-online.target" ]; 128 after = [ "network-online.target" ]; 129 restartTriggers = [ config.environment.etc."nomad.json".source ]; 130 131 path = cfg.extraPackages ++ (with pkgs; [ 132 # Client mode requires at least the following: 133 coreutils 134 iproute2 135 iptables 136 ]); 137 138 serviceConfig = mkMerge [ 139 { 140 DynamicUser = cfg.dropPrivileges; 141 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 142 ExecStart = "${cfg.package}/bin/nomad agent -config=/etc/nomad.json" + 143 concatMapStrings (path: " -config=${path}") cfg.extraSettingsPaths + 144 concatMapStrings (path: " -plugin-dir=${path}/bin") cfg.extraSettingsPlugins; 145 KillMode = "process"; 146 KillSignal = "SIGINT"; 147 LimitNOFILE = 65536; 148 LimitNPROC = "infinity"; 149 OOMScoreAdjust = -1000; 150 Restart = "on-failure"; 151 RestartSec = 2; 152 TasksMax = "infinity"; 153 } 154 (mkIf cfg.enableDocker { 155 SupplementaryGroups = "docker"; # space-separated string 156 }) 157 (mkIf (cfg.settings.data_dir == "/var/lib/nomad") { 158 StateDirectory = "nomad"; 159 }) 160 ]; 161 162 unitConfig = { 163 StartLimitIntervalSec = 10; 164 StartLimitBurst = 3; 165 }; 166 }; 167 168 assertions = [ 169 { 170 assertion = cfg.dropPrivileges -> cfg.settings.data_dir == "/var/lib/nomad"; 171 message = "settings.data_dir must be equal to \"/var/lib/nomad\" if dropPrivileges is true"; 172 } 173 ]; 174 175 # Docker support requires the Docker daemon to be running. 176 virtualisation.docker.enable = mkIf cfg.enableDocker true; 177 }; 178}