diff --git a/modules/anycast_healthchecker/default.nix b/modules/anycast_healthchecker/default.nix new file mode 100644 index 0000000..2683a09 --- /dev/null +++ b/modules/anycast_healthchecker/default.nix @@ -0,0 +1,122 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.clerie.anycast_healthchecker; + configFile = pkgs.writeText "anycast-healthchecker.conf" '' + [DEFAULT] + interface = lo + + [daemon] + pidfile = /run/anycast-healthchecker/anycast-healthchecker.pid + ipv4 = true + ipv6 = true + bird_conf = /var/lib/anycast-healthchecker/anycast-prefixes.conf + bird6_conf = /var/lib/anycast-healthchecker/anycast-prefixes6.conf + bird_variable = ACAST_PS_ADVERTISE + bird6_variable = ACAST6_PS_ADVERTISE + bird_reconfigure_cmd = birdc configure + bird6_reconfigure_cmd = birdc configure + dummy_ip_prefix = 10.189.200.255/32 + dummy_ip6_prefix = 2001:db8::1/128 + bird_keep_changes = false + bird6_keep_changes = false + bird_changes_counter = 128 + bird6_changes_counter = 128 + purge_ip_prefixes = false + loglevel = debug + log_maxbytes = 104857600 + log_backups = 8 + json_stdout = false + json_log_file = false + json_log_server = false + ''; + + checksDir = pkgs.writeTextDir "checks.conf" ( + concatStringsSep "\n" ( + mapAttrsToList ( + name: check: '' + [${name}] + ip_prefix = ${check.ip_prefix} + check_cmd = ${check.cmd} + '' + ( + concatStringsSep "\n" ( + optional (check.timeout != null) "check_timeout = ${toString check.timeout}" + ++ optional (check.rise != null) "check_rise = ${toString check.rise}" + ++ optional (check.fail != null) "check_fail = ${toString check.fail}" + ++ optional (check.interval != null) "check_interval = ${toString check.interval}" + ) + ) + ) cfg.checks + ) + ); + + checkOpts = { config, ... }@moduleAttrs: { + + options = { + + enable = mkOption { + type = types.bool; + default = true; + }; + timeout = mkOption { + type = with types; nullOr int; + default = null; + }; + rise = mkOption { + type = with types; nullOr int; + default = null; + }; + fail = mkOption { + type = with types; nullOr int; + default = null; + }; + interval = mkOption { + type = with types; nullOr int; + default = null; + }; + ip_prefix = mkOption { + type = types.str; + }; + cmd = mkOption { + type = types.str; + default = "${pkgs.curl}/bin/curl --fail --silent http://${moduleAttrs.config.ip_prefix}"; + }; + }; + + }; + +in { + + options = { + + clerie.anycast_healthchecker = { + + enable = mkEnableOption "anycast healthchecker"; + + checks = mkOption { + type = with types; attrsOf (submodule checkOpts); + }; + + }; + + }; + + + config = mkIf cfg.enable { + + systemd.services.anycast_healthchecker = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + RuntimeDirectory = "anycast-healthchecker"; + StateDirectory = "anycast-healthchecker"; + User = "bird2"; + Group = "bird2"; + ExecStart = "${pkgs.anycast_healthchecker}/bin/anycast-healthchecker -f ${configFile} -d ${checksDir}"; + }; + path = with pkgs; [ bird2 ]; + }; + + }; +}