diff --git a/morph/grid/local/grid.nix b/morph/grid/local/grid.nix index efdfa1f955d9864e56acb20bb0c5810f22c47643..e672f3d14ef5f7389511a818921a9a75c6e948fe 100644 --- a/morph/grid/local/grid.nix +++ b/morph/grid/local/grid.nix @@ -59,7 +59,7 @@ let grid = { publicKeyPath = toString ./. + "/${grid-config.publicKeyPath}"; privateKeyPath = toString ./. + "/${grid-config.privateKeyPath}"; - inherit (grid-config) monitoringvpnEndpoint; + inherit (grid-config) monitoringvpnEndpoint letsEncryptAdminEmail; }; # Configure deployment management authorization for all systems in the grid. services.private-storage.deployment = { @@ -77,7 +77,7 @@ let grid.monitoringvpnIPv4 = "172.23.23.11"; grid.publicIPv4 = "192.168.67.21"; grid.issuer = { - inherit (grid-config) letsEncryptAdminEmail issuerDomains allowedChargeOrigins; + inherit (grid-config) issuerDomains allowedChargeOrigins; }; }; }; @@ -115,19 +115,18 @@ let monitoring = { imports = [ gridlib.monitoring - (gridlib.customize-monitoring { - inherit paymentExporterTargets - blackboxExporterHttpsTargets; - inherit (grid-config) letsEncryptAdminEmail monitoringDomains; - googleOAuthClientID = grid-config.monitoringGoogleOAuthClientID; - enableSlackAlert = false; - stateVersion = "19.09"; - }) grid-module ]; config = { grid.monitoringvpnIPv4 = "172.23.23.1"; grid.publicIPv4 = "192.168.67.24"; + grid.monitoring = { + inherit paymentExporterTargets blackboxExporterHttpsTargets; + inherit (grid-config) monitoringDomains; + googleOAuthClientID = grid-config.monitoringGoogleOAuthClientID; + enableSlackAlert = false; + }; + system.stateVersion = "19.09"; }; }; diff --git a/morph/grid/production/grid.nix b/morph/grid/production/grid.nix index 33b9726ffe7dc90a6d6528fb3d0da7d2fa401430..ab45d4ba7f67e71383d28120bd925ac3a05f04ef 100644 --- a/morph/grid/production/grid.nix +++ b/morph/grid/production/grid.nix @@ -21,7 +21,7 @@ let grid = { publicKeyPath = toString ./. + "/${grid-config.publicKeyPath}"; privateKeyPath = toString ./. + "/${grid-config.privateKeyPath}"; - inherit (grid-config) monitoringvpnEndpoint; + inherit (grid-config) monitoringvpnEndpoint letsEncryptAdminEmail; }; # Configure deployment management authorization for all systems in the grid. services.private-storage.deployment = { @@ -39,7 +39,7 @@ let config = { grid.monitoringvpnIPv4 = "172.23.23.11"; grid.issuer = { - inherit (grid-config) letsEncryptAdminEmail issuerDomains allowedChargeOrigins; + inherit (grid-config) issuerDomains allowedChargeOrigins; }; }; }; @@ -48,18 +48,17 @@ let imports = [ gridlib.monitoring gridlib.hardware-aws - (gridlib.customize-monitoring { - inherit paymentExporterTargets - blackboxExporterHttpsTargets; - inherit (grid-config) letsEncryptAdminEmail monitoringDomains; - googleOAuthClientID = grid-config.monitoringGoogleOAuthClientID; - enableSlackAlert = true; - stateVersion = "19.09"; - }) grid-module ]; config = { grid.monitoringvpnIPv4 = "172.23.23.1"; + grid.monitoring = { + inherit paymentExporterTargets blackboxExporterHttpsTargets; + inherit (grid-config) monitoringDomains; + googleOAuthClientID = grid-config.monitoringGoogleOAuthClientID; + enableSlackAlert = true; + }; + system.stateVersion = "19.09"; }; }; diff --git a/morph/grid/testing/grid.nix b/morph/grid/testing/grid.nix index 8d3e5483f398a5db5c422d197a80ab6f41542d15..19839ae83fa16c31adf0fcd9e3727a8304f8dd6c 100644 --- a/morph/grid/testing/grid.nix +++ b/morph/grid/testing/grid.nix @@ -21,7 +21,7 @@ let grid = { publicKeyPath = toString ./. + "/${grid-config.publicKeyPath}"; privateKeyPath = toString ./. + "/${grid-config.privateKeyPath}"; - inherit (grid-config) monitoringvpnEndpoint; + inherit (grid-config) monitoringvpnEndpoint letsEncryptAdminEmail; }; # Configure deployment management authorization for all systems in the grid. services.private-storage.deployment = { @@ -39,7 +39,7 @@ let config = { grid.monitoringvpnIPv4 = "172.23.23.11"; grid.issuer = { - inherit (grid-config) letsEncryptAdminEmail issuerDomains allowedChargeOrigins; + inherit (grid-config) issuerDomains allowedChargeOrigins; }; }; }; @@ -64,18 +64,17 @@ let imports = [ gridlib.monitoring gridlib.hardware-aws - (gridlib.customize-monitoring { - inherit paymentExporterTargets - blackboxExporterHttpsTargets; - inherit (grid-config) letsEncryptAdminEmail monitoringDomains; - googleOAuthClientID = grid-config.monitoringGoogleOAuthClientID; - enableSlackAlert = true; - stateVersion = "19.09"; - }) grid-module ]; config = { grid.monitoringvpnIPv4 = "172.23.23.1"; + grid.monitoring = { + inherit paymentExporterTargets blackboxExporterHttpsTargets; + inherit (grid-config) monitoringDomains; + googleOAuthClientID = grid-config.monitoringGoogleOAuthClientID; + enableSlackAlert = true; + }; + system.stateVersion = "19.09"; }; }; diff --git a/morph/lib/base.nix b/morph/lib/base.nix index 9b698b9629c12c7343fbd2e9eea5d2ee599b612e..c814631f7e04ee6c8a5206893863d6e6d6fe9e97 100644 --- a/morph/lib/base.nix +++ b/morph/lib/base.nix @@ -30,6 +30,14 @@ The domain name and port of the monitoring VPN endpoint. ''; }; + + letsEncryptAdminEmail = lib.mkOption { + type = lib.types.str; + description = '' + A string giving an email address to use for Let's Encrypt registration and + certificate issuance. + ''; + }; }; # Any extra NixOS modules to load on all our servers. Note that just diff --git a/morph/lib/customize-monitoring.nix b/morph/lib/customize-monitoring.nix deleted file mode 100644 index 841a0d04b9bb462eb9d62742a514c9fa412f3206..0000000000000000000000000000000000000000 --- a/morph/lib/customize-monitoring.nix +++ /dev/null @@ -1,101 +0,0 @@ -# Define a function which returns a value which fills in all the holes left by -# ``monitoring.nix``. -{ - # A string giving an email address to use for Let's Encrypt registration and - # certificate issuance. - letsEncryptAdminEmail - - # A list of strings giving the domain names that point at this monitoring - # system. These will all be included in Let's Encrypt certificate. -, monitoringDomains - - # A list of VPN clients (IP addresses or hostnames) as strings indicating - # which nodes to scrape "nginxExporter" metrics from. -, nginxExporterTargets ? [] - - # A list of VPN clients (IP addresses or hostnames) as strings indicating - # which nodes to scrape PaymentServer metrics from. -, paymentExporterTargets ? [] - - # A list of HTTPS servers (URLs, IP addresses or hostnames) as strings indicating - # which nodes the BlackboxExporter should scrape HTTP and TLS metrics from. -, blackboxExporterHttpsTargets ? [] - - # A string containing the GSuite OAuth2 ClientID to use to authenticate - # logins to Grafana. -, googleOAuthClientID - - # Whether to enable alerting via Slack. - # When true requires a grafana-slack-url file (see private-keys/README.rst). -, enableSlackAlert ? false - - # A string giving the NixOS state version for the system. -, stateVersion -, ... -}: -{ config, ... }: -let - inherit (config.grid) publicKeyPath privateKeyPath monitoringvpnIPv4; -in { - deployment.secrets = let - # When Grafana SSO is disabled there is not necessarily any client secret - # available. Avoid telling morph that there is one in this case (so it - # avoids trying to read it and then failing). Even if the secret did - # exist, if SSO is disabled there's no point sending the secret to the - # server. - # - # Also, we have to define this whole secret here so that we can configure - # it completely or not at all. morph gets angry if we half configure it - # (say, by just omitting the "source" value). - grafanaSSO = - if googleOAuthClientID == "" - then { } - else { - "grafana-google-sso-secret" = { - source = "${privateKeyPath}/grafana-google-sso.secret"; - destination = "/run/keys/grafana-google-sso.secret"; - owner.user = config.systemd.services.grafana.serviceConfig.User; - owner.group = config.users.users.grafana.group; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "grafana.service"]; - }; - "grafana-admin-password" = { - source = "${privateKeyPath}/grafana-admin.password"; - destination = "/run/keys/grafana-admin.password"; - owner.user = config.systemd.services.grafana.serviceConfig.User; - owner.group = config.users.users.grafana.group; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "grafana.service"]; - }; - }; - grafanaSlackUrl = - if !enableSlackAlert - then { } - else { - "grafana-slack-url" = { - source = "${privateKeyPath}/grafana-slack-url"; - destination = "/run/keys/grafana-slack-url"; - owner.user = config.systemd.services.grafana.serviceConfig.User; - owner.group = config.users.users.grafana.group; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "grafana.service"]; - }; - }; - in - grafanaSSO // grafanaSlackUrl; - - services.private-storage.monitoring.prometheus = { - inherit nginxExporterTargets; - inherit paymentExporterTargets; - inherit blackboxExporterHttpsTargets; - }; - - services.private-storage.monitoring.grafana = { - inherit letsEncryptAdminEmail; - inherit googleOAuthClientID; - inherit enableSlackAlert; - domains = monitoringDomains; - }; - - system.stateVersion = stateVersion; -} diff --git a/morph/lib/default.nix b/morph/lib/default.nix index 766fda5102589fbdc32e26c17fbc94731ab71a73..88c83bc2211da2e00e69f95d7d2110d3ee636cc3 100644 --- a/morph/lib/default.nix +++ b/morph/lib/default.nix @@ -9,9 +9,7 @@ issuer = import ./issuer.nix; storage = import ./storage.nix; - monitoring = import ./monitoring.nix; - customize-monitoring = import ./customize-monitoring.nix; modules = builtins.toString ../../nixos/modules; diff --git a/morph/lib/issuer.nix b/morph/lib/issuer.nix index b2d48c2cee8cb914d7c3c9acedfcaf9ad2997178..69b0527cd74e0752ded6ffbe7513db126f0613f5 100644 --- a/morph/lib/issuer.nix +++ b/morph/lib/issuer.nix @@ -3,7 +3,7 @@ { lib, config, ...}: let inherit (config.grid) publicKeyPath privateKeyPath monitoringvpnEndpoint monitoringvpnIPv4; - inherit (config.grid.issuer) letsEncryptAdminEmail issuerDomains allowedChargeOrigins; + inherit (config.grid.issuer) issuerDomains allowedChargeOrigins; in { imports = [ ../../nixos/modules/monitoring/vpn/client.nix @@ -11,14 +11,6 @@ in { ]; options.grid.issuer = { - letsEncryptAdminEmail = lib.mkOption { - type = lib.types.str; - description = '' - A string giving an email address to use for Let's Encrypt registration and - certificate issuance. - ''; - }; - issuerDomains = lib.mkOption { type = lib.types.listOf lib.types.str; description = '' @@ -82,7 +74,8 @@ in { stripeSecretKeyPath = config.deployment.secrets.stripe-secret-key.destination; database = "SQLite3"; databasePath = "${config.fileSystems."zkapissuer-data".mountPoint}/vouchers.sqlite3"; - inherit letsEncryptAdminEmail allowedChargeOrigins; + inherit (config.grid) letsEncryptAdminEmail; + inherit allowedChargeOrigins; domains = issuerDomains; }; diff --git a/morph/lib/monitoring.nix b/morph/lib/monitoring.nix index ca1db1a029775b37e749b4462545dd539c66fda2..c52d19e872e9db547c4ba53df83db130da815312 100644 --- a/morph/lib/monitoring.nix +++ b/morph/lib/monitoring.nix @@ -1,8 +1,9 @@ -# Similar to ``issuer.nix`` but for a "monitoring"-type system. Holes are -# filled by ``customize-monitoring.nix``. +# This contains all of the NixOS system configuration necessary to specify an +# "monitoring"-type system. { lib, config, nodes, ...}: let - inherit (config.grid) publicKeyPath privateKeyPath monitoringvpnIPv4; + cfg = config.grid.monitoring; + inherit (config.grid) publicKeyPath privateKeyPath monitoringvpnIPv4 letsEncryptAdminEmail; # This collects information about monitored hosts from their configuration for use below. monitoringHosts = lib.mapAttrsToList (name: node: rec { @@ -35,27 +36,100 @@ in { # ../../nixos/modules/monitoring/server/loki.nix ]; + options.grid.monitoring = { + paymentExporterTargets = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = '' + A list of VPN clients (IP addresses or hostnames) as strings indicating + which nodes to scrape PaymentServer metrics from. + ''; + }; + + blackboxExporterHttpsTargets = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = '' + A list of HTTPS servers (URLs, IP addresses or hostnames) as strings indicating + which nodes the BlackboxExporter should scrape HTTP and TLS metrics from. + ''; + }; + + monitoringDomains = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = '' + A list of strings giving the domain names that point at this monitoring + system. These will all be included in Let's Encrypt certificate. + ''; + }; + + + googleOAuthClientID = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + A string containing the GSuite OAuth2 ClientID to use to authenticate + logins to Grafana. + ''; + }; + + enableSlackAlert = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Whether to enable alerting via Slack. + When true requires a grafana-slack-url file (see private-keys/README.rst). + ''; + }; + }; + config = { - deployment = { - secrets = { + deployment.secrets = lib.mkMerge [ + { "monitoringvpn-private-key" = { - destination = "/run/keys/monitoringvpn/server.key"; - source = "${privateKeyPath}/monitoringvpn/server.key"; - owner.user = "root"; - owner.group = "root"; - permissions = "0400"; - action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; + destination = "/run/keys/monitoringvpn/server.key"; + source = "${privateKeyPath}/monitoringvpn/server.key"; + owner.user = "root"; + owner.group = "root"; + permissions = "0400"; + action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; }; "monitoringvpn-preshared-key" = { - destination = "/run/keys/monitoringvpn/preshared.key"; - source = "${privateKeyPath}/monitoringvpn/preshared.key"; - owner.user = "root"; - owner.group = "root"; + destination = "/run/keys/monitoringvpn/preshared.key"; + source = "${privateKeyPath}/monitoringvpn/preshared.key"; + owner.user = "root"; + owner.group = "root"; + permissions = "0400"; + action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; + }; + } + (lib.mkIf (cfg.googleOAuthClientID != "") { + "grafana-google-sso-secret" = { + source = "${privateKeyPath}/grafana-google-sso.secret"; + destination = "/run/keys/grafana-google-sso.secret"; + owner.user = config.systemd.services.grafana.serviceConfig.User; + owner.group = config.users.users.grafana.group; permissions = "0400"; - action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"]; + action = ["sudo" "systemctl" "restart" "grafana.service"]; }; - }; - }; + "grafana-admin-password" = { + source = "${privateKeyPath}/grafana-admin.password"; + destination = "/run/keys/grafana-admin.password"; + owner.user = config.systemd.services.grafana.serviceConfig.User; + owner.group = config.users.users.grafana.group; + permissions = "0400"; + action = ["sudo" "systemctl" "restart" "grafana.service"]; + }; + }) + (lib.mkIf cfg.enableSlackAlert { + "grafana-slack-url" = { + source = "${privateKeyPath}/grafana-slack-url"; + destination = "/run/keys/grafana-slack-url"; + owner.user = config.systemd.services.grafana.serviceConfig.User; + owner.group = config.users.users.grafana.group; + permissions = "0400"; + action = ["sudo" "systemctl" "restart" "grafana.service"]; + }; + }) + ]; networking.hosts = hostsMap; @@ -68,6 +142,14 @@ in { services.private-storage.monitoring.prometheus = { inherit nodeExporterTargets; + inherit (cfg) paymentExporterTargets blackboxExporterHttpsTargets; + nginxExporterTargets = []; + }; + + services.private-storage.monitoring.grafana = { + inherit (cfg) googleOAuthClientID enableSlackAlert ; + inherit letsEncryptAdminEmail; + domains = cfg.monitoringDomains; }; }; }