at master 4.4 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 format = pkgs.formats.json { }; 9 commonOptions = 10 { 11 pkgName, 12 flavour ? pkgName, 13 }: 14 lib.mkOption { 15 default = { }; 16 description = '' 17 Attribute set of ${flavour} instances. 18 Creates independent `${flavour}-''${name}.service` systemd units for each instance defined here. 19 ''; 20 type = 21 with lib.types; 22 attrsOf ( 23 submodule ( 24 { name, ... }: 25 { 26 options = { 27 enable = lib.mkEnableOption "this ${flavour} instance" // { 28 default = true; 29 }; 30 31 package = lib.mkPackageOption pkgs pkgName { }; 32 33 user = lib.mkOption { 34 type = types.str; 35 default = "root"; 36 description = '' 37 User under which this instance runs. 38 ''; 39 }; 40 41 group = lib.mkOption { 42 type = types.str; 43 default = "root"; 44 description = '' 45 Group under which this instance runs. 46 ''; 47 }; 48 49 settings = lib.mkOption { 50 type = types.submodule { 51 freeformType = format.type; 52 53 options = { 54 pid_file = lib.mkOption { 55 default = "/run/${flavour}/${name}.pid"; 56 type = types.str; 57 description = '' 58 Path to use for the pid file. 59 ''; 60 }; 61 }; 62 }; 63 64 default = { }; 65 66 description = 67 let 68 upstreamDocs = 69 if flavour == "vault-agent" then 70 "https://developer.hashicorp.com/vault/docs/agent#configuration-file-options" 71 else 72 "https://github.com/hashicorp/consul-template/blob/main/docs/configuration.md#configuration-file"; 73 in 74 '' 75 Free-form settings written directly to the `config.json` file. 76 Refer to <${upstreamDocs}> for supported values. 77 78 ::: {.note} 79 Resulting format is JSON not HCL. 80 Refer to <https://www.hcl2json.com/> if you are unsure how to convert HCL options to JSON. 81 ::: 82 ''; 83 }; 84 }; 85 } 86 ) 87 ); 88 }; 89 90 createAgentInstance = 91 { 92 instance, 93 name, 94 flavour, 95 }: 96 let 97 configFile = format.generate "${name}.json" instance.settings; 98 in 99 lib.mkIf (instance.enable) { 100 description = "${flavour} daemon - ${name}"; 101 wantedBy = [ "multi-user.target" ]; 102 after = [ "network.target" ]; 103 path = [ pkgs.getent ]; 104 startLimitIntervalSec = 60; 105 startLimitBurst = 3; 106 serviceConfig = { 107 User = instance.user; 108 Group = instance.group; 109 RuntimeDirectory = flavour; 110 ExecStart = "${lib.getExe instance.package} ${ 111 lib.optionalString (flavour == "vault-agent") "agent" 112 } -config ${configFile}"; 113 ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID"; 114 KillSignal = "SIGINT"; 115 TimeoutStopSec = "30s"; 116 Restart = "on-failure"; 117 }; 118 }; 119in 120{ 121 options = { 122 services.consul-template.instances = commonOptions { pkgName = "consul-template"; }; 123 services.vault-agent.instances = commonOptions { 124 pkgName = "vault"; 125 flavour = "vault-agent"; 126 }; 127 }; 128 129 config = lib.mkMerge ( 130 map 131 ( 132 flavour: 133 let 134 cfg = config.services.${flavour}; 135 in 136 lib.mkIf (cfg.instances != { }) { 137 systemd.services = lib.mapAttrs' ( 138 name: instance: 139 lib.nameValuePair "${flavour}-${name}" (createAgentInstance { 140 inherit name instance flavour; 141 }) 142 ) cfg.instances; 143 } 144 ) 145 [ 146 "consul-template" 147 "vault-agent" 148 ] 149 ); 150 151 meta.maintainers = with lib.maintainers; [ 152 emilylange 153 tcheronneau 154 ]; 155}