dotfiles/nixos/modules/hashicorp-envoy.nix

196 lines
5.3 KiB
Nix
Raw Normal View History

{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.services.hashicorp-envoy;
serviceFormat = pkgs.formats.json {};
serviceFile = name: value:
if value.type == "normal"
then serviceFormat.generate "${name}-service.json" {service = value.service;}
else serviceFormat.generate "${name}-service.json" value.service;
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)];
};
type = mkOption {
description =
mdDoc ''
'';
type = with types; enum ["ingress" "terminating" "normal"];
default = "normal";
};
environment = mkOption {
description =
mdDoc ''
'';
type = with types; attrsOf str;
default = {};
};
adminBind = mkOption {
description =
mdDoc ''
'';
type = types.str;
};
address = mkOption {
description =
mdDoc ''
'';
type = types.str;
default = "0.0.0.0:19000";
};
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;
};
extraConsulArgs = mkOption {
description =
mdDoc ''
'';
type = with types; listOf str;
default = [];
};
};
});
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 =
if value.type == "normal"
then ''
${value.consulPackage}/bin/consul services register ${serviceFile name value}
''
else ''
${value.consulPackage}/bin/consul config write ${serviceFile name value}
'';
postStop =
if value.type == "normal"
then ''
${value.consulPackage}/bin/consul services deregister -id=${value.service.id}
''
else ''
${value.consulPackage}/bin/consul config delete -filename ${serviceFile name value}
'';
script = let
startEnvoy =
pkgs.writeShellScript "start_envoy_${name}.sh"
''
exec ${value.consulPackage}/bin/consul connect envoy \
${concatStringsSep " " value.extraConsulArgs} \
${optionalString (value.type == "normal") ''
-sidecar-for ${value.service.id} \
''} \
${optionalString (value.type == "ingress") ''
-gateway=ingress \
-register \
-service ${value.service.name} \
''} \
-admin-bind ${value.adminBind} \
-address ${value.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 =
if value.hotRestart
then "${pkgs.coreutils}/bin/kill -HUP $MAINPID"
else null;
KillMode = "control-group";
KillSignal = "SIGINT";
LimitNOFILE = 65536;
LimitNPROC = "infinity";
OOMScoreAdjust = -1000;
Restart = "always";
RestartSec = 2;
TasksMax = "infinity";
RuntimeDirectory = name;
};
}
);
};
}