{ config, lib, pkgs, domain, vhosts ? { }, ... }: with lib; let cfg = config.infra.gatus; vhost = vhosts.${cfg.hostname} or { }; port = vhost.ports.http or 8081; # Auto-infer monitored hosts from the central vhosts map. # Only entries with a non-empty `gatus_health` path are monitored. monitored = lib.filterAttrs (_: v: (v.gatus_health or "") != "") vhosts; autoEndpoints = lib.mapAttrsToList (name: v: { name = v.description or name; url = "https://${name}${v.gatus_health}"; interval = "1m"; conditions = [ "[STATUS] == 200" "[RESPONSE_TIME] < 1000" ]; } ) monitored; in { options.infra.gatus = { enable = mkEnableOption "Gatus status page behind nginx"; hostname = mkOption { type = types.str; default = "status.${domain}"; description = "Virtual host name serving the Gatus status page"; }; title = mkOption { type = types.str; default = "Status"; description = "Title shown in the Gatus UI"; }; endpoints = mkOption { type = types.listOf types.attrs; default = [ ]; description = '' Gatus endpoint definitions. See https://gatus.io/docs/configure-endpoints ''; }; extraSettings = mkOption { type = types.attrs; default = { }; description = "Extra settings merged into services.gatus.settings"; }; }; config = mkIf cfg.enable { services.gatus = { enable = true; settings = mkMerge [ { web.port = port; storage = { type = "sqlite"; path = "/var/lib/gatus/data.db"; }; ui.title = cfg.title; endpoints = autoEndpoints ++ cfg.endpoints; } cfg.extraSettings ]; }; }; }