diff options
Diffstat (limited to 'nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix')
-rw-r--r-- | nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix | 136 |
1 files changed, 82 insertions, 54 deletions
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix index 3bc61fba158f..19ee3ae6f7da 100644 --- a/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix +++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix @@ -3,7 +3,7 @@ with lib; let - json = pkgs.formats.json { }; + yaml = pkgs.formats.yaml { }; cfg = config.services.prometheus; checkConfigEnabled = (lib.isBool cfg.checkConfig && cfg.checkConfig) @@ -11,8 +11,6 @@ let workingDir = "/var/lib/" + cfg.stateDir; - prometheusYmlOut = "${workingDir}/prometheus-substituted.yaml"; - triggerReload = pkgs.writeShellScriptBin "trigger-reload-prometheus" '' PATH="${makeBinPath (with pkgs; [ systemd ])}" if systemctl -q is-active prometheus.service; then @@ -33,12 +31,12 @@ let if checkConfigEnabled then pkgs.runCommandLocal "${name}-${replaceStrings [" "] [""] what}-checked" - { buildInputs = [ cfg.package ]; } '' + { buildInputs = [ cfg.package.cli ]; } '' ln -s ${file} $out promtool ${what} $out '' else file; - generatedPrometheusYml = json.generate "prometheus.yml" promConfig; + generatedPrometheusYml = yaml.generate "prometheus.yml" promConfig; # This becomes the main config file for Prometheus promConfig = { @@ -73,7 +71,8 @@ let "--web.listen-address=${cfg.listenAddress}:${builtins.toString cfg.port}" "--alertmanager.notification-queue-capacity=${toString cfg.alertmanagerNotificationQueueCapacity}" ] ++ optional (cfg.webExternalUrl != null) "--web.external-url=${cfg.webExternalUrl}" - ++ optional (cfg.retentionTime != null) "--storage.tsdb.retention.time=${cfg.retentionTime}"; + ++ optional (cfg.retentionTime != null) "--storage.tsdb.retention.time=${cfg.retentionTime}" + ++ optional (cfg.webConfigFile != null) "--web.config.file=${cfg.webConfigFile}"; filterValidPrometheus = filterAttrsListRecursive (n: v: !(n == "_module" || v == null)); filterAttrsListRecursive = pred: x: @@ -99,14 +98,14 @@ let mkDefOpt = type: defaultStr: description: mkOpt type (description + '' - Defaults to <literal>${defaultStr}</literal> in prometheus - when set to <literal>null</literal>. + Defaults to ````${defaultStr}```` in prometheus + when set to `null`. ''); mkOpt = type: description: mkOption { type = types.nullOr type; default = null; - inherit description; + description = lib.mdDoc description; }; mkSdConfigModule = extraOptions: types.submodule { @@ -251,7 +250,7 @@ let authorization = mkOption { type = types.nullOr types.attrs; default = null; - description = '' + description = lib.mdDoc '' Sets the `Authorization` header on every scrape request with the configured credentials. ''; }; @@ -288,7 +287,7 @@ let If honor_labels is set to "false", label conflicts are resolved by renaming conflicting labels in the scraped data - to "exported_<original-label>" (for example + to "exported_\<original-label\>" (for example "exported_instance", "exported_job") and then attaching server-side labels. This is useful for use cases such as federation, where all labels specified in the target should @@ -299,10 +298,10 @@ let honor_timestamps controls whether Prometheus respects the timestamps present in scraped data. - If honor_timestamps is set to <literal>true</literal>, the timestamps of the metrics exposed + If honor_timestamps is set to `true`, the timestamps of the metrics exposed by the target will be used. - If honor_timestamps is set to <literal>false</literal>, the timestamps of the metrics exposed + If honor_timestamps is set to `false`, the timestamps of the metrics exposed by the target will be ignored. ''; @@ -323,13 +322,13 @@ let bearer_token = mkOpt types.str '' Sets the `Authorization` header on every scrape request with the configured bearer token. It is mutually exclusive with - <option>bearer_token_file</option>. + {option}`bearer_token_file`. ''; bearer_token_file = mkOpt types.str '' Sets the `Authorization` header on every scrape request with the bearer token read from the configured file. It is mutually - exclusive with <option>bearer_token</option>. + exclusive with {option}`bearer_token`. ''; tls_config = mkOpt promTypes.tls_config '' @@ -379,7 +378,7 @@ let gce_sd_configs = mkOpt (types.listOf promTypes.gce_sd_config) '' List of Google Compute Engine service discovery configurations. - See <link xlink:href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config">the relevant Prometheus configuration docs</link> + See [the relevant Prometheus configuration docs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config) for more detail. ''; @@ -591,7 +590,7 @@ let allow_stale = mkOpt types.bool '' Allow stale Consul results - (see <link xlink:href="https://www.consul.io/api/index.html#consistency-modes"/>). + (see <https://www.consul.io/api/index.html#consistency-modes>). Will reduce load on Consul. ''; @@ -632,16 +631,16 @@ let options = { name = mkOption { type = types.str; - description = '' + description = lib.mdDoc '' Name of the filter. The available filters are listed in the upstream documentation: - Services: <link xlink:href="https://docs.docker.com/engine/api/v1.40/#operation/ServiceList"/> - Tasks: <link xlink:href="https://docs.docker.com/engine/api/v1.40/#operation/TaskList"/> - Nodes: <link xlink:href="https://docs.docker.com/engine/api/v1.40/#operation/NodeList"/> + Services: <https://docs.docker.com/engine/api/v1.40/#operation/ServiceList> + Tasks: <https://docs.docker.com/engine/api/v1.40/#operation/TaskList> + Nodes: <https://docs.docker.com/engine/api/v1.40/#operation/NodeList> ''; }; values = mkOption { type = types.str; - description = '' + description = lib.mdDoc '' Value for the filter. ''; }; @@ -664,7 +663,7 @@ let promTypes.dockerswarm_sd_config = mkDockerSdConfigModule { role = mkOption { type = types.enum [ "services" "tasks" "nodes" ]; - description = '' + description = lib.mdDoc '' Role of the targets to retrieve. Must be `services`, `tasks`, or `nodes`. ''; }; @@ -707,12 +706,12 @@ let access_key = mkOpt types.str '' The AWS API key id. If blank, the environment variable - <literal>AWS_ACCESS_KEY_ID</literal> is used. + `AWS_ACCESS_KEY_ID` is used. ''; secret_key = mkOpt types.str '' The AWS API key secret. If blank, the environment variable - <literal>AWS_SECRET_ACCESS_KEY</literal> is used. + `AWS_SECRET_ACCESS_KEY` is used. ''; profile = mkOpt types.str '' @@ -738,8 +737,8 @@ let options = { name = mkOption { type = types.str; - description = '' - See <link xlink:href="https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html">this list</link> + description = lib.mdDoc '' + See [this list](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html) for the available filters. ''; }; @@ -747,7 +746,7 @@ let values = mkOption { type = types.listOf types.str; default = [ ]; - description = '' + description = lib.mdDoc '' Value of the filter. ''; }; @@ -806,7 +805,7 @@ let filter = mkOpt types.str '' Filter can be used optionally to filter the instance list by other criteria Syntax of this filter string is described here in the filter - query parameter section: <link xlink:href="https://cloud.google.com/compute/docs/reference/latest/instances/list"/>. + query parameter section: <https://cloud.google.com/compute/docs/reference/latest/instances/list>. ''; refresh_interval = mkDefOpt types.str "60s" '' @@ -822,7 +821,7 @@ let The tag separator used to separate concatenated GCE instance network tags. See the GCP documentation on network tags for more information: - <link xlink:href="https://cloud.google.com/vpc/docs/add-remove-network-tags"/> + <https://cloud.google.com/vpc/docs/add-remove-network-tags> ''; }; }; @@ -917,7 +916,7 @@ let options = { role = mkOption { type = types.str; - description = '' + description = lib.mdDoc '' Selector role ''; }; @@ -976,11 +975,11 @@ let ''; access_key = mkOpt types.str '' - The AWS API keys. If blank, the environment variable <literal>AWS_ACCESS_KEY_ID</literal> is used. + The AWS API keys. If blank, the environment variable `AWS_ACCESS_KEY_ID` is used. ''; secret_key = mkOpt types.str '' - The AWS API keys. If blank, the environment variable <literal>AWS_SECRET_ACCESS_KEY</literal> is used. + The AWS API keys. If blank, the environment variable `AWS_SECRET_ACCESS_KEY` is used. ''; profile = mkOpt types.str '' @@ -1030,14 +1029,14 @@ let auth_token = mkOpt types.str '' Optional authentication information for token-based authentication: - <link xlink:href="https://docs.mesosphere.com/1.11/security/ent/iam-api/#passing-an-authentication-token"/> - It is mutually exclusive with <literal>auth_token_file</literal> and other authentication mechanisms. + <https://docs.mesosphere.com/1.11/security/ent/iam-api/#passing-an-authentication-token> + It is mutually exclusive with `auth_token_file` and other authentication mechanisms. ''; auth_token_file = mkOpt types.str '' Optional authentication information for token-based authentication: - <link xlink:href="https://docs.mesosphere.com/1.11/security/ent/iam-api/#passing-an-authentication-token"/> - It is mutually exclusive with <literal>auth_token</literal> and other authentication mechanisms. + <https://docs.mesosphere.com/1.11/security/ent/iam-api/#passing-an-authentication-token> + It is mutually exclusive with `auth_token` and other authentication mechanisms. ''; }; @@ -1222,7 +1221,7 @@ let role = mkOption { type = types.enum [ "instance" "baremetal" ]; - description = '' + description = lib.mdDoc '' Role of the targets to retrieve. Must be `instance` or `baremetal`. ''; }; @@ -1299,7 +1298,7 @@ let }; groups = mkOpt (types.listOf types.str) '' - A list of groups for which targets are retrieved, only supported when targeting the <literal>container</literal> role. + A list of groups for which targets are retrieved, only supported when targeting the `container` role. If omitted all containers owned by the requesting account are scraped. ''; @@ -1409,7 +1408,7 @@ let ''; action = - mkDefOpt (types.enum [ "replace" "keep" "drop" "hashmod" "labelmap" "labeldrop" "labelkeep" ]) "replace" '' + mkDefOpt (types.enum [ "replace" "lowercase" "uppercase" "keep" "drop" "hashmod" "labelmap" "labeldrop" "labelkeep" ]) "replace" '' Action to perform based on regex matching. ''; }; @@ -1563,13 +1562,7 @@ in options.services.prometheus = { - enable = mkOption { - type = types.bool; - default = false; - description = lib.mdDoc '' - Enable the Prometheus monitoring daemon. - ''; - }; + enable = mkEnableOption (lib.mdDoc "Prometheus monitoring daemon"); package = mkOption { type = types.package; @@ -1621,7 +1614,7 @@ in The following property holds: switching to a configuration (`switch-to-configuration`) that changes the prometheus - configuration only finishes successully when prometheus has finished + configuration only finishes successfully when prometheus has finished loading the new configuration. ''; }; @@ -1725,20 +1718,28 @@ in ''; }; + webConfigFile = mkOption { + type = types.nullOr types.path; + default = null; + description = lib.mdDoc '' + Specifies which file should be used as web.config.file and be passed on startup. + See https://prometheus.io/docs/prometheus/latest/configuration/https/ for valid options. + ''; + }; + checkConfig = mkOption { type = with types; either bool (enum [ "syntax-only" ]); default = true; example = "syntax-only"; - description = '' - Check configuration with <literal>promtool - check</literal>. The call to <literal>promtool</literal> is + description = lib.mdDoc '' + Check configuration with `promtool check`. The call to `promtool` is subject to sandboxing by Nix. If you use credentials stored in external files - (<literal>password_file</literal>, <literal>bearer_token_file</literal>, etc), - they will not be visible to <literal>promtool</literal> + (`password_file`, `bearer_token_file`, etc), + they will not be visible to `promtool` and it will report errors, despite a correct configuration. - To resolve this, you may set this option to <literal>"syntax-only"</literal> + To resolve this, you may set this option to `"syntax-only"` in order to only syntax check the Prometheus configuration. ''; }; @@ -1797,6 +1798,33 @@ in WorkingDirectory = workingDir; StateDirectory = cfg.stateDir; StateDirectoryMode = "0700"; + # Hardening + AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; + CapabilityBoundingSet = if (cfg.port < 1024) then [ "CAP_NET_BIND_SERVICE" ] else [ "" ]; + DeviceAllow = [ "/dev/null rw" ]; + DevicePolicy = "strict"; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + PrivateUsers = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "full"; + RemoveIPC = true; + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ "@system-service" "~@privileged" ]; }; }; # prometheus-config-reload will activate after prometheus. However, what we |