{ config, lib, pkgs, ... }: with lib; let cfg = config.services.hashicorp-envoy; serviceFormat = pkgs.formats.json {}; in { options.services.hashicorp-envoy = mkOption { description = mdDoc '' ''; type = types.attrsOf (types.submodule { options = { service = mkOption { description = mdDoc '' ''; type = with types; oneOf [ serviceFormat.type (listOf serviceFormat.type) ]; }; environment = mkOption { description = mdDoc '' ''; type = with types; attrsOf str; default = {}; }; adminBind = mkOption { description = mdDoc '' ''; type = types.str; }; drainTime = mkOption { description = mdDoc '' ''; type = types.int; default = 15; }; parentShutdownTime = mkOption { description = mdDoc '' ''; type = types.int; default = 20; }; hotRestart = mkOption { description = mdDoc '' ''; type = types.bool; default = false; }; consulPackage = mkOption { description = mdDoc '' ''; type = types.package; default = pkgs.consul; }; envoyPackage = mkOption { description = mdDoc '' ''; type = types.package; default = pkgs.envoy; }; }; }); default = {}; }; config = { systemd.services = flip mapAttrs' cfg (name: value: nameValuePair "hashicorp-envoy-${name}" { description = name; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "network-online.target" ]; path = [ value.envoyPackage ]; restartIfChanged = true; preStart = '' ${value.consulPackage}/bin/consul services register \ ${serviceFormat.generate "${name}-service.json" { service = value.service; }} ''; postStop = '' ${value.consulPackage}/bin/consul services deregister -id=${value.service.id} ''; script = let address = value.service.connect.sidecar_service.address or "0.0.0.0" + ":" + toString value.service.connect.sidecar_service.port or "19000"; startEnvoy = pkgs.writeShellScript "start_envoy.sh" '' exec ${value.consulPackage}/bin/consul connect envoy \ -sidecar-for ${value.service.id} \ -admin-bind ${value.adminBind} \ -address ${address} \ ${optionalString value.hotRestart '' -- \ $([[ $RESTART_EPOCH == 0 ]] && printf -- "--use-dynamic-base-id --base-id-path $RUNTIME_DIRECTORY/id") \ $([[ $RESTART_EPOCH == 0 ]] || printf -- "--base-id $(cat $RUNTIME_DIRECTORY/id)") \ --restart-epoch $RESTART_EPOCH \ --drain-time-s ${toString value.drainTime} \ --parent-shutdown-time-s ${toString value.parentShutdownTime} ''} ''; in if value.hotRestart then "exec ${pkgs.python3}/bin/python ${value.envoyPackage.src}/restarter/hot-restarter.py ${startEnvoy}" else "exec ${startEnvoy}"; environment = value.environment; serviceConfig = { ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; KillMode = "control-group"; KillSignal = "SIGINT"; LimitNOFILE = 65536; LimitNPROC = "infinity"; OOMScoreAdjust = -1000; Restart = "always"; RestartSec = 2; TasksMax = "infinity"; RuntimeDirectory = name; }; } ); }; }