{ 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 ]; }; }; }