diff --git a/DEPLOYMENT-NOTES.rst b/DEPLOYMENT-NOTES.rst index 5de83386dbb939cc3cfe2a8b68c198f218934933..0a7ea52e0bfb20e77f86797ead1778d614a2a720 100644 --- a/DEPLOYMENT-NOTES.rst +++ b/DEPLOYMENT-NOTES.rst @@ -1,6 +1,8 @@ Deployment notes ================ +- 2021-09-30 `Enable alerting <https://whetstone.privatestorage.io/privatestorage/PrivateStorageio/-/merge_requests/185>`_ needs a secret in ``private-keys/grafana-slack-url`` looking like the template in ``morph/grid/local/private-keys/grafana-slack-url`` and pointing to the secret API endpoint URL saved in `this 1Password entry <https://privatestorage.1password.com/vaults/7flqasy5hhhmlbtp5qozd3j4ga/allitems/cgznskz2oix2tyx5xyntwaos5i>`_ (or create a new secret URL at https://www.slack.com/apps/A0F7XDUAZ). + - 2021-09-07 `Manage access to payment metrics <https://whetstone.privatestorage.io/privatestorage/PrivateStorageio/-/merge_requests/146>`_ requires moving and chown'ing the PaymentServer database on the ``payments`` host:: mkdir /var/lib/zkapissuer diff --git a/morph/grid/local/grid.nix b/morph/grid/local/grid.nix index 59880af8b91173ec8c4480f459ed6c862474ba38..15afcc8f600018f2cd50fe7f8a0cf4383da27ead 100644 --- a/morph/grid/local/grid.nix +++ b/morph/grid/local/grid.nix @@ -108,6 +108,7 @@ let inherit hostsMap vpnClientIPs nodeExporterTargets paymentExporterTargets; inherit (grid-config) letsEncryptAdminEmail; googleOAuthClientID = grid-config.monitoringGoogleOAuthClientID; + enableSlackAlert = false; monitoringvpnIPv4 = "172.23.23.1"; stateVersion = "19.09"; }) diff --git a/morph/grid/local/private-keys/README.rst b/morph/grid/local/private-keys/README.rst index 684bf942a8010129f49cfcf79f5df1b60965ae45..91670ac1a0ea6ee2c68df71ff196d010bdba8637 100644 --- a/morph/grid/local/private-keys/README.rst +++ b/morph/grid/local/private-keys/README.rst @@ -19,6 +19,13 @@ grafana-admin.password This is the initial admin password for the Grafana web admin on the monitoring host. +grafana-slack-url +----------------- + +This file is read by Grafana's systemd service to set an environment variable with a secret Slack WebHook URL to post alerts to. +The only line in the file should be ``SLACKURL=`` with the secret URL. +Use the url from `this 1Password entry <https://privatestorage.1password.com/vaults/7flqasy5hhhmlbtp5qozd3j4ga/allitems/cgznskz2oix2tyx5xyntwaos5i>`_ or get a new secret URL for your Slack channel at https://www.slack.com/apps/A0F7XDUAZ. + stripe.secret ------------- diff --git a/morph/grid/local/private-keys/grafana-slack-url b/morph/grid/local/private-keys/grafana-slack-url new file mode 100644 index 0000000000000000000000000000000000000000..cb7dd1aec785a557fef6082a7570bc8c56728f14 --- /dev/null +++ b/morph/grid/local/private-keys/grafana-slack-url @@ -0,0 +1,2 @@ +SLACKURL=https://hooks.slack.com/services/x/y/z + diff --git a/morph/grid/production/grid.nix b/morph/grid/production/grid.nix index 3e0d41a5e6caabdc2c958f7bad0ae0ff10243c92..ec0c1b37f996dd836f6011425f114471a2ccde0a 100644 --- a/morph/grid/production/grid.nix +++ b/morph/grid/production/grid.nix @@ -48,6 +48,7 @@ let inherit hostsMap vpnClientIPs nodeExporterTargets paymentExporterTargets; inherit (grid-config) letsEncryptAdminEmail; googleOAuthClientID = grid-config.monitoringGoogleOAuthClientID; + enableSlackAlert = true; monitoringvpnIPv4 = "172.23.23.1"; stateVersion = "19.09"; }) diff --git a/morph/grid/testing/grid.nix b/morph/grid/testing/grid.nix index 383fe740674992042a899ac391c100640ad5dcd7..7a304e11cfd7ec3fbef3f8efa2417a9004132c42 100644 --- a/morph/grid/testing/grid.nix +++ b/morph/grid/testing/grid.nix @@ -61,6 +61,7 @@ let inherit hostsMap vpnClientIPs nodeExporterTargets paymentExporterTargets; inherit (grid-config) letsEncryptAdminEmail; googleOAuthClientID = grid-config.monitoringGoogleOAuthClientID; + enableSlackAlert = true; monitoringvpnIPv4 = "172.23.23.1"; stateVersion = "19.09"; }) diff --git a/morph/lib/customize-monitoring.nix b/morph/lib/customize-monitoring.nix index 19a800f1fa806c09f132f2bb2769869a30c65ec2..d9842692481777a7e65b70208b5c0246b3209d1a 100644 --- a/morph/lib/customize-monitoring.nix +++ b/morph/lib/customize-monitoring.nix @@ -32,6 +32,10 @@ # 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 , ... @@ -71,12 +75,25 @@ in { 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"]; + }; + }; monitoringvpn = { "monitoringvpn-private-key".source = "${privateKeyPath}/monitoringvpn/server.key"; "monitoringvpn-preshared-key".source = "${privateKeyPath}/monitoringvpn/preshared.key"; }; in - grafanaSSO // monitoringvpn; + grafanaSSO // grafanaSlackUrl // monitoringvpn; networking.hosts = hostsMap; @@ -96,6 +113,7 @@ in { services.private-storage.monitoring.grafana = { inherit letsEncryptAdminEmail; inherit googleOAuthClientID; + inherit enableSlackAlert; domain = "${config.networking.hostName}.${config.networking.domain}"; }; diff --git a/nixos/modules/monitoring/server/grafana-config/payments.json b/nixos/modules/monitoring/server/grafana-dashboards/payments.json similarity index 100% rename from nixos/modules/monitoring/server/grafana-config/payments.json rename to nixos/modules/monitoring/server/grafana-dashboards/payments.json diff --git a/nixos/modules/monitoring/server/grafana-config/resources-overview.json b/nixos/modules/monitoring/server/grafana-dashboards/resources-overview.json similarity index 100% rename from nixos/modules/monitoring/server/grafana-config/resources-overview.json rename to nixos/modules/monitoring/server/grafana-dashboards/resources-overview.json diff --git a/nixos/modules/monitoring/server/grafana.nix b/nixos/modules/monitoring/server/grafana.nix index c23150238241db561bae52aa50e4878b6961f9e6..1783782ce7e395f9201dd93e2386f4eed4bf003e 100644 --- a/nixos/modules/monitoring/server/grafana.nix +++ b/nixos/modules/monitoring/server/grafana.nix @@ -62,12 +62,36 @@ in { default = /run/keys/grafana-admin.password; description = "A file containing the password for the Grafana Admin account."; }; + enableSlackAlert = lib.mkOption + { type = lib.types.bool; + default = false; + description = '' + Enables the slack alerter. Expects a file that contains + the definition of an environment variable named SLACKURL + pointing to the secret Slack Web Hook URL in + grafanaSlackUrlFile (see below). + ''; + }; + grafanaSlackUrlFile = lib.mkOption + { type = lib.types.path; + default = /run/keys/grafana-slack-url; + description = '' + Where to find the Grafana Systemd EnvironmentFile that + sets the secret SLACKURL environment variable. + ''; + }; }; config = { # Port 80 for ACME ssl retrieval only. 443 for nginx -> grafana. networking.firewall.allowedTCPPorts = [ 80 443 ]; + # We pass the secret Slack URL using an environment variable. + systemd.services.grafana.serviceConfig.EnvironmentFile = + if cfg.enableSlackAlert + then [ cfg.grafanaSlackUrlFile ] + else [ ]; + services.grafana = { enable = true; domain = cfg.domain; @@ -119,8 +143,23 @@ in { # See https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards dashboards = [{ name = "provisioned"; - options.path = ./grafana-config; + options.path = ./grafana-dashboards; }]; + # See https://grafana.com/docs/grafana/latest/administration/provisioning/#example-alert-notification-channels-config-file + notifiers = [ ] ++ (lib.optionals (cfg.enableSlackAlert) [{ + uid = "slack-notifier-1"; + name = "Slack"; + type = "slack"; + is_default = true; + send_reminder = false; + settings = { + username = "${cfg.domain}"; + uploadImage = true; + }; + secure_settings = { + url = "$SLACKURL"; + }; + }]); }; };