summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/services/networking/keepalived/default.nix62
-rw-r--r--nixos/modules/services/networking/keepalived/vrrp-instance-options.nix (renamed from nixos/modules/services/networking/keepalived/vrrp-options.nix)14
-rw-r--r--nixos/modules/services/networking/keepalived/vrrp-script-options.nix64
3 files changed, 138 insertions, 2 deletions
diff --git a/nixos/modules/services/networking/keepalived/default.nix b/nixos/modules/services/networking/keepalived/default.nix
index 378cd9365848..c9ac2ee25990 100644
--- a/nixos/modules/services/networking/keepalived/default.nix
+++ b/nixos/modules/services/networking/keepalived/default.nix
@@ -8,10 +8,12 @@ let
 
   keepalivedConf = pkgs.writeText "keepalived.conf" ''
     global_defs {
+      ${optionalString cfg.enableScriptSecurity "enable_script_security"}
       ${snmpGlobalDefs}
       ${cfg.extraGlobalDefs}
     }
 
+    ${vrrpScriptStr}
     ${vrrpInstancesStr}
     ${cfg.extraConfig}
   '';
@@ -26,6 +28,22 @@ let
     + optionalString enableTraps "enable_traps"
   );
 
+  vrrpScriptStr = concatStringsSep "\n" (map (s:
+    ''
+      vrrp_script ${s.name} {
+        script "${s.script}"
+        interval ${toString s.interval}
+        fall ${toString s.fall}
+        rise ${toString s.rise}
+        timeout ${toString s.timeout}
+        weight ${toString s.weight}
+        user ${s.user} ${optionalString (s.group != null) s.group}
+
+        ${s.extraConfig}
+      }
+    ''
+  ) vrrpScripts);
+
   vrrpInstancesStr = concatStringsSep "\n" (map (i:
     ''
       vrrp_instance ${i.name} {
@@ -49,6 +67,18 @@ let
           ${concatMapStringsSep "\n" virtualIpLine i.virtualIps}
         }
 
+        ${optionalString (builtins.length i.trackScripts > 0) ''
+          track_script {
+            ${concatStringsSep "\n" i.trackScripts}
+          }
+        ''}
+
+        ${optionalString (builtins.length i.trackInterfaces > 0) ''
+          track_interface {
+            ${concatStringsSep "\n" i.trackInterfaces}
+          }
+        ''}
+
         ${i.extraConfig}
       }
     ''
@@ -64,6 +94,12 @@ let
 
   notNullOrEmpty = s: !(s == null || s == "");
 
+  vrrpScripts = mapAttrsToList (name: config:
+    {
+      inherit name;
+    } // config
+  ) cfg.vrrpScripts;
+
   vrrpInstances = mapAttrsToList (iName: iConfig:
     {
       name = iName;
@@ -86,7 +122,8 @@ let
     { assertion = !i.vmacXmitBase || i.useVmac;
       message = "services.keepalived.vrrpInstances.${i.name}.vmacXmitBase has no effect when services.keepalived.vrrpInstances.${i.name}.useVmac is not set.";
     }
-  ] ++ flatten (map (virtualIpAssertions i.name) i.virtualIps);
+  ] ++ flatten (map (virtualIpAssertions i.name) i.virtualIps)
+    ++ flatten (map (vrrpScriptAssertion i.name) i.trackScripts);
 
   virtualIpAssertions = vrrpName: ip: [
     { assertion = ip.addr != "";
@@ -94,6 +131,11 @@ let
     }
   ];
 
+  vrrpScriptAssertion = vrrpName: scriptName: {
+    assertion = builtins.hasAttr scriptName cfg.vrrpScripts;
+    message = "services.keepalived.vrrpInstances.${vrrpName} trackscript ${scriptName} is not defined in services.keepalived.vrrpScripts.";
+  };
+
   pidFile = "/run/keepalived.pid";
 
 in
@@ -110,6 +152,14 @@ in
         '';
       };
 
+      enableScriptSecurity = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Don't run scripts configured to be run as root if any part of the path is writable by a non-root user.
+        '';
+      };
+
       snmp = {
 
         enable = mkOption {
@@ -181,8 +231,16 @@ in
 
       };
 
+      vrrpScripts = mkOption {
+        type = types.attrsOf (types.submodule (import ./vrrp-script-options.nix {
+          inherit lib;
+        }));
+        default = {};
+        description = "Declarative vrrp script config";
+      };
+
       vrrpInstances = mkOption {
-        type = types.attrsOf (types.submodule (import ./vrrp-options.nix {
+        type = types.attrsOf (types.submodule (import ./vrrp-instance-options.nix {
           inherit lib;
         }));
         default = {};
diff --git a/nixos/modules/services/networking/keepalived/vrrp-options.nix b/nixos/modules/services/networking/keepalived/vrrp-instance-options.nix
index 79eff3ae5419..85b9bc337726 100644
--- a/nixos/modules/services/networking/keepalived/vrrp-options.nix
+++ b/nixos/modules/services/networking/keepalived/vrrp-instance-options.nix
@@ -108,6 +108,20 @@ with lib;
       description = "Declarative vhost config";
     };
 
+    trackScripts = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = [ "chk_cmd1" "chk_cmd2" ];
+      description = "List of script names to invoke for health tracking.";
+    };
+
+    trackInterfaces = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = [ "eth0" "eth1" ];
+      description = "List of network interfaces to monitor for health tracking.";
+    };
+
     extraConfig = mkOption {
       type = types.lines;
       default = "";
diff --git a/nixos/modules/services/networking/keepalived/vrrp-script-options.nix b/nixos/modules/services/networking/keepalived/vrrp-script-options.nix
new file mode 100644
index 000000000000..a3f794c40a89
--- /dev/null
+++ b/nixos/modules/services/networking/keepalived/vrrp-script-options.nix
@@ -0,0 +1,64 @@
+{ lib } :
+
+with lib;
+with lib.types;
+{
+  options = {
+
+    script = mkOption {
+      type = str;
+      example = "\${pkgs.curl} -f http://localhost:80";
+      description = "(Path of) Script command to execute followed by args, i.e. cmd [args]...";
+    };
+
+    interval = mkOption {
+      type = int;
+      default = 1;
+      description = "Seconds between script invocations.";
+    };
+
+    timeout = mkOption {
+      type = int;
+      default = 5;
+      description = "Seconds after which script is considered to have failed.";
+    };
+
+    weight = mkOption {
+      type = int;
+      default = 0;
+      description = "Following a failure, adjust the priority by this weight.";
+    };
+
+    rise = mkOption {
+      type = int;
+      default = 5;
+      description = "Required number of successes for OK transition.";
+    };
+
+    fall = mkOption {
+      type = int;
+      default = 3;
+      description = "Required number of failures for KO transition.";
+    };
+
+    user = mkOption {
+      type = str;
+      default = "keepalived_script";
+      description = "Name of user to run the script under.";
+    };
+
+    group = mkOption {
+      type = nullOr str;
+      default = null;
+      description = "Name of group to run the script under. Defaults to user group.";
+    };
+
+    extraConfig = mkOption {
+      type = lines;
+      default = "";
+      description = "Extra lines to be added verbatim to the vrrp_script section.";
+    };
+
+  };
+
+}