at 23.05-pre 6.5 kB view raw
1{ config, pkgs, lib, ... }: 2 3with lib; 4 5let 6 cfg = config.services.prometheus.alertmanager; 7 mkConfigFile = pkgs.writeText "alertmanager.yml" (builtins.toJSON cfg.configuration); 8 9 checkedConfig = file: pkgs.runCommand "checked-config" { buildInputs = [ cfg.package ]; } '' 10 ln -s ${file} $out 11 amtool check-config $out 12 ''; 13 14 alertmanagerYml = let 15 yml = if cfg.configText != null then 16 pkgs.writeText "alertmanager.yml" cfg.configText 17 else mkConfigFile; 18 in checkedConfig yml; 19 20 cmdlineArgs = cfg.extraFlags ++ [ 21 "--config.file /tmp/alert-manager-substituted.yaml" 22 "--web.listen-address ${cfg.listenAddress}:${toString cfg.port}" 23 "--log.level ${cfg.logLevel}" 24 "--storage.path /var/lib/alertmanager" 25 (toString (map (peer: "--cluster.peer ${peer}:9094") cfg.clusterPeers)) 26 ] ++ (optional (cfg.webExternalUrl != null) 27 "--web.external-url ${cfg.webExternalUrl}" 28 ) ++ (optional (cfg.logFormat != null) 29 "--log.format ${cfg.logFormat}" 30 ); 31in { 32 imports = [ 33 (mkRemovedOptionModule [ "services" "prometheus" "alertmanager" "user" ] "The alertmanager service is now using systemd's DynamicUser mechanism which obviates a user setting.") 34 (mkRemovedOptionModule [ "services" "prometheus" "alertmanager" "group" ] "The alertmanager service is now using systemd's DynamicUser mechanism which obviates a group setting.") 35 (mkRemovedOptionModule [ "services" "prometheus" "alertmanagerURL" ] '' 36 Due to incompatibility, the alertmanagerURL option has been removed, 37 please use 'services.prometheus2.alertmanagers' instead. 38 '') 39 ]; 40 41 options = { 42 services.prometheus.alertmanager = { 43 enable = mkEnableOption (lib.mdDoc "Prometheus Alertmanager"); 44 45 package = mkOption { 46 type = types.package; 47 default = pkgs.prometheus-alertmanager; 48 defaultText = literalExpression "pkgs.alertmanager"; 49 description = lib.mdDoc '' 50 Package that should be used for alertmanager. 51 ''; 52 }; 53 54 configuration = mkOption { 55 type = types.nullOr types.attrs; 56 default = null; 57 description = lib.mdDoc '' 58 Alertmanager configuration as nix attribute set. 59 ''; 60 }; 61 62 configText = mkOption { 63 type = types.nullOr types.lines; 64 default = null; 65 description = lib.mdDoc '' 66 Alertmanager configuration as YAML text. If non-null, this option 67 defines the text that is written to alertmanager.yml. If null, the 68 contents of alertmanager.yml is generated from the structured config 69 options. 70 ''; 71 }; 72 73 logFormat = mkOption { 74 type = types.nullOr types.str; 75 default = null; 76 description = lib.mdDoc '' 77 If set use a syslog logger or JSON logging. 78 ''; 79 }; 80 81 logLevel = mkOption { 82 type = types.enum ["debug" "info" "warn" "error" "fatal"]; 83 default = "warn"; 84 description = lib.mdDoc '' 85 Only log messages with the given severity or above. 86 ''; 87 }; 88 89 webExternalUrl = mkOption { 90 type = types.nullOr types.str; 91 default = null; 92 description = lib.mdDoc '' 93 The URL under which Alertmanager is externally reachable (for example, if Alertmanager is served via a reverse proxy). 94 Used for generating relative and absolute links back to Alertmanager itself. 95 If the URL has a path portion, it will be used to prefix all HTTP endoints served by Alertmanager. 96 If omitted, relevant URL components will be derived automatically. 97 ''; 98 }; 99 100 listenAddress = mkOption { 101 type = types.str; 102 default = ""; 103 description = lib.mdDoc '' 104 Address to listen on for the web interface and API. Empty string will listen on all interfaces. 105 "localhost" will listen on 127.0.0.1 (but not ::1). 106 ''; 107 }; 108 109 port = mkOption { 110 type = types.int; 111 default = 9093; 112 description = lib.mdDoc '' 113 Port to listen on for the web interface and API. 114 ''; 115 }; 116 117 openFirewall = mkOption { 118 type = types.bool; 119 default = false; 120 description = lib.mdDoc '' 121 Open port in firewall for incoming connections. 122 ''; 123 }; 124 125 clusterPeers = mkOption { 126 type = types.listOf types.str; 127 default = []; 128 description = lib.mdDoc '' 129 Initial peers for HA cluster. 130 ''; 131 }; 132 133 extraFlags = mkOption { 134 type = types.listOf types.str; 135 default = []; 136 description = lib.mdDoc '' 137 Extra commandline options when launching the Alertmanager. 138 ''; 139 }; 140 141 environmentFile = mkOption { 142 type = types.nullOr types.path; 143 default = null; 144 example = "/root/alertmanager.env"; 145 description = lib.mdDoc '' 146 File to load as environment file. Environment variables 147 from this file will be interpolated into the config file 148 using envsubst with this syntax: 149 `$ENVIRONMENT ''${VARIABLE}` 150 ''; 151 }; 152 }; 153 }; 154 155 config = mkMerge [ 156 (mkIf cfg.enable { 157 assertions = singleton { 158 assertion = cfg.configuration != null || cfg.configText != null; 159 message = "Can not enable alertmanager without a configuration. " 160 + "Set either the `configuration` or `configText` attribute."; 161 }; 162 }) 163 (mkIf cfg.enable { 164 networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port; 165 166 systemd.services.alertmanager = { 167 wantedBy = [ "multi-user.target" ]; 168 after = [ "network-online.target" ]; 169 preStart = '' 170 ${lib.getBin pkgs.envsubst}/bin/envsubst -o "/tmp/alert-manager-substituted.yaml" \ 171 -i "${alertmanagerYml}" 172 ''; 173 serviceConfig = { 174 Restart = "always"; 175 StateDirectory = "alertmanager"; 176 DynamicUser = true; # implies PrivateTmp 177 EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile; 178 WorkingDirectory = "/tmp"; 179 ExecStart = "${cfg.package}/bin/alertmanager" + 180 optionalString (length cmdlineArgs != 0) (" \\\n " + 181 concatStringsSep " \\\n " cmdlineArgs); 182 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 183 }; 184 }; 185 }) 186 ]; 187}