1{ config, pkgs, lib, ... }:
2
3with lib;
4
5let
6 cfg = config.services.prometheus;
7
8 workingDir = "/var/lib/" + cfg.stateDir;
9
10 # a wrapper that verifies that the configuration is valid
11 promtoolCheck = what: name: file:
12 if cfg.checkConfig then
13 pkgs.runCommandNoCCLocal
14 "${name}-${replaceStrings [" "] [""] what}-checked"
15 { buildInputs = [ cfg.package ]; } ''
16 ln -s ${file} $out
17 promtool ${what} $out
18 '' else file;
19
20 # Pretty-print JSON to a file
21 writePrettyJSON = name: x:
22 pkgs.runCommandNoCCLocal name {} ''
23 echo '${builtins.toJSON x}' | ${pkgs.jq}/bin/jq . > $out
24 '';
25
26 generatedPrometheusYml = writePrettyJSON "prometheus.yml" promConfig;
27
28 # This becomes the main config file for Prometheus
29 promConfig = {
30 global = filterValidPrometheus cfg.globalConfig;
31 rule_files = map (promtoolCheck "check rules" "rules") (cfg.ruleFiles ++ [
32 (pkgs.writeText "prometheus.rules" (concatStringsSep "\n" cfg.rules))
33 ]);
34 scrape_configs = filterValidPrometheus cfg.scrapeConfigs;
35 remote_write = filterValidPrometheus cfg.remoteWrite;
36 remote_read = filterValidPrometheus cfg.remoteRead;
37 alerting = {
38 inherit (cfg) alertmanagers;
39 };
40 };
41
42 prometheusYml = let
43 yml = if cfg.configText != null then
44 pkgs.writeText "prometheus.yml" cfg.configText
45 else generatedPrometheusYml;
46 in promtoolCheck "check config" "prometheus.yml" yml;
47
48 cmdlineArgs = cfg.extraFlags ++ [
49 "--storage.tsdb.path=${workingDir}/data/"
50 "--config.file=/run/prometheus/prometheus-substituted.yaml"
51 "--web.listen-address=${cfg.listenAddress}:${builtins.toString cfg.port}"
52 "--alertmanager.notification-queue-capacity=${toString cfg.alertmanagerNotificationQueueCapacity}"
53 "--alertmanager.timeout=${toString cfg.alertmanagerTimeout}s"
54 ] ++ optional (cfg.webExternalUrl != null) "--web.external-url=${cfg.webExternalUrl}"
55 ++ optional (cfg.retentionTime != null) "--storage.tsdb.retention.time=${cfg.retentionTime}";
56
57 filterValidPrometheus = filterAttrsListRecursive (n: v: !(n == "_module" || v == null));
58 filterAttrsListRecursive = pred: x:
59 if isAttrs x then
60 listToAttrs (
61 concatMap (name:
62 let v = x.${name}; in
63 if pred name v then [
64 (nameValuePair name (filterAttrsListRecursive pred v))
65 ] else []
66 ) (attrNames x)
67 )
68 else if isList x then
69 map (filterAttrsListRecursive pred) x
70 else x;
71
72 mkDefOpt = type : defaultStr : description : mkOpt type (description + ''
73
74 Defaults to <literal>${defaultStr}</literal> in prometheus
75 when set to <literal>null</literal>.
76 '');
77
78 mkOpt = type : description : mkOption {
79 type = types.nullOr type;
80 default = null;
81 inherit description;
82 };
83
84 promTypes.globalConfig = types.submodule {
85 options = {
86 scrape_interval = mkDefOpt types.str "1m" ''
87 How frequently to scrape targets by default.
88 '';
89
90 scrape_timeout = mkDefOpt types.str "10s" ''
91 How long until a scrape request times out.
92 '';
93
94 evaluation_interval = mkDefOpt types.str "1m" ''
95 How frequently to evaluate rules by default.
96 '';
97
98 external_labels = mkOpt (types.attrsOf types.str) ''
99 The labels to add to any time series or alerts when
100 communicating with external systems (federation, remote
101 storage, Alertmanager).
102 '';
103 };
104 };
105
106 promTypes.remote_read = types.submodule {
107 options = {
108 url = mkOption {
109 type = types.str;
110 description = ''
111 ServerName extension to indicate the name of the server.
112 http://tools.ietf.org/html/rfc4366#section-3.1
113 '';
114 };
115 name = mkOpt types.str ''
116 Name of the remote read config, which if specified must be unique among remote read configs.
117 The name will be used in metrics and logging in place of a generated value to help users distinguish between
118 remote read configs.
119 '';
120 required_matchers = mkOpt (types.attrsOf types.str) ''
121 An optional list of equality matchers which have to be
122 present in a selector to query the remote read endpoint.
123 '';
124 remote_timeout = mkOpt types.str ''
125 Timeout for requests to the remote read endpoint.
126 '';
127 read_recent = mkOpt types.bool ''
128 Whether reads should be made for queries for time ranges that
129 the local storage should have complete data for.
130 '';
131 basic_auth = mkOpt (types.submodule {
132 options = {
133 username = mkOption {
134 type = types.str;
135 description = ''
136 HTTP username
137 '';
138 };
139 password = mkOpt types.str "HTTP password";
140 password_file = mkOpt types.str "HTTP password file";
141 };
142 }) ''
143 Sets the `Authorization` header on every remote read request with the
144 configured username and password.
145 password and password_file are mutually exclusive.
146 '';
147 bearer_token = mkOpt types.str ''
148 Sets the `Authorization` header on every remote read request with
149 the configured bearer token. It is mutually exclusive with `bearer_token_file`.
150 '';
151 bearer_token_file = mkOpt types.str ''
152 Sets the `Authorization` header on every remote read request with the bearer token
153 read from the configured file. It is mutually exclusive with `bearer_token`.
154 '';
155 tls_config = mkOpt promTypes.tls_config ''
156 Configures the remote read request's TLS settings.
157 '';
158 proxy_url = mkOpt types.str "Optional Proxy URL.";
159 };
160 };
161
162 promTypes.remote_write = types.submodule {
163 options = {
164 url = mkOption {
165 type = types.str;
166 description = ''
167 ServerName extension to indicate the name of the server.
168 http://tools.ietf.org/html/rfc4366#section-3.1
169 '';
170 };
171 remote_timeout = mkOpt types.str ''
172 Timeout for requests to the remote write endpoint.
173 '';
174 write_relabel_configs = mkOpt (types.listOf promTypes.relabel_config) ''
175 List of remote write relabel configurations.
176 '';
177 name = mkOpt types.str ''
178 Name of the remote write config, which if specified must be unique among remote write configs.
179 The name will be used in metrics and logging in place of a generated value to help users distinguish between
180 remote write configs.
181 '';
182 basic_auth = mkOpt (types.submodule {
183 options = {
184 username = mkOption {
185 type = types.str;
186 description = ''
187 HTTP username
188 '';
189 };
190 password = mkOpt types.str "HTTP password";
191 password_file = mkOpt types.str "HTTP password file";
192 };
193 }) ''
194 Sets the `Authorization` header on every remote write request with the
195 configured username and password.
196 password and password_file are mutually exclusive.
197 '';
198 bearer_token = mkOpt types.str ''
199 Sets the `Authorization` header on every remote write request with
200 the configured bearer token. It is mutually exclusive with `bearer_token_file`.
201 '';
202 bearer_token_file = mkOpt types.str ''
203 Sets the `Authorization` header on every remote write request with the bearer token
204 read from the configured file. It is mutually exclusive with `bearer_token`.
205 '';
206 tls_config = mkOpt promTypes.tls_config ''
207 Configures the remote write request's TLS settings.
208 '';
209 proxy_url = mkOpt types.str "Optional Proxy URL.";
210 queue_config = mkOpt (types.submodule {
211 options = {
212 capacity = mkOpt types.int ''
213 Number of samples to buffer per shard before we block reading of more
214 samples from the WAL. It is recommended to have enough capacity in each
215 shard to buffer several requests to keep throughput up while processing
216 occasional slow remote requests.
217 '';
218 max_shards = mkOpt types.int ''
219 Maximum number of shards, i.e. amount of concurrency.
220 '';
221 min_shards = mkOpt types.int ''
222 Minimum number of shards, i.e. amount of concurrency.
223 '';
224 max_samples_per_send = mkOpt types.int ''
225 Maximum number of samples per send.
226 '';
227 batch_send_deadline = mkOpt types.str ''
228 Maximum time a sample will wait in buffer.
229 '';
230 min_backoff = mkOpt types.str ''
231 Initial retry delay. Gets doubled for every retry.
232 '';
233 max_backoff = mkOpt types.str ''
234 Maximum retry delay.
235 '';
236 };
237 }) ''
238 Configures the queue used to write to remote storage.
239 '';
240 metadata_config = mkOpt (types.submodule {
241 options = {
242 send = mkOpt types.bool ''
243 Whether metric metadata is sent to remote storage or not.
244 '';
245 send_interval = mkOpt types.str ''
246 How frequently metric metadata is sent to remote storage.
247 '';
248 };
249 }) ''
250 Configures the sending of series metadata to remote storage.
251 Metadata configuration is subject to change at any point
252 or be removed in future releases.
253 '';
254 };
255 };
256
257 promTypes.scrape_config = types.submodule {
258 options = {
259 job_name = mkOption {
260 type = types.str;
261 description = ''
262 The job name assigned to scraped metrics by default.
263 '';
264 };
265 scrape_interval = mkOpt types.str ''
266 How frequently to scrape targets from this job. Defaults to the
267 globally configured default.
268 '';
269
270 scrape_timeout = mkOpt types.str ''
271 Per-target timeout when scraping this job. Defaults to the
272 globally configured default.
273 '';
274
275 metrics_path = mkDefOpt types.str "/metrics" ''
276 The HTTP resource path on which to fetch metrics from targets.
277 '';
278
279 honor_labels = mkDefOpt types.bool "false" ''
280 Controls how Prometheus handles conflicts between labels
281 that are already present in scraped data and labels that
282 Prometheus would attach server-side ("job" and "instance"
283 labels, manually configured target labels, and labels
284 generated by service discovery implementations).
285
286 If honor_labels is set to "true", label conflicts are
287 resolved by keeping label values from the scraped data and
288 ignoring the conflicting server-side labels.
289
290 If honor_labels is set to "false", label conflicts are
291 resolved by renaming conflicting labels in the scraped data
292 to "exported_<original-label>" (for example
293 "exported_instance", "exported_job") and then attaching
294 server-side labels. This is useful for use cases such as
295 federation, where all labels specified in the target should
296 be preserved.
297 '';
298
299 honor_timestamps = mkDefOpt types.bool "true" ''
300 honor_timestamps controls whether Prometheus respects the timestamps present
301 in scraped data.
302
303 If honor_timestamps is set to <literal>true</literal>, the timestamps of the metrics exposed
304 by the target will be used.
305
306 If honor_timestamps is set to <literal>false</literal>, the timestamps of the metrics exposed
307 by the target will be ignored.
308 '';
309
310 scheme = mkDefOpt (types.enum ["http" "https"]) "http" ''
311 The URL scheme with which to fetch metrics from targets.
312 '';
313
314 params = mkOpt (types.attrsOf (types.listOf types.str)) ''
315 Optional HTTP URL parameters.
316 '';
317
318 basic_auth = mkOpt (types.submodule {
319 options = {
320 username = mkOption {
321 type = types.str;
322 description = ''
323 HTTP username
324 '';
325 };
326 password = mkOption {
327 type = types.str;
328 description = ''
329 HTTP password
330 '';
331 };
332 };
333 }) ''
334 Optional http login credentials for metrics scraping.
335 '';
336
337 bearer_token = mkOpt types.str ''
338 Sets the `Authorization` header on every scrape request with
339 the configured bearer token. It is mutually exclusive with
340 <option>bearer_token_file</option>.
341 '';
342
343 bearer_token_file = mkOpt types.str ''
344 Sets the `Authorization` header on every scrape request with
345 the bearer token read from the configured file. It is mutually
346 exclusive with <option>bearer_token</option>.
347 '';
348
349 tls_config = mkOpt promTypes.tls_config ''
350 Configures the scrape request's TLS settings.
351 '';
352
353 proxy_url = mkOpt types.str ''
354 Optional proxy URL.
355 '';
356
357 ec2_sd_configs = mkOpt (types.listOf promTypes.ec2_sd_config) ''
358 List of EC2 service discovery configurations.
359 '';
360
361 dns_sd_configs = mkOpt (types.listOf promTypes.dns_sd_config) ''
362 List of DNS service discovery configurations.
363 '';
364
365 consul_sd_configs = mkOpt (types.listOf promTypes.consul_sd_config) ''
366 List of Consul service discovery configurations.
367 '';
368
369 file_sd_configs = mkOpt (types.listOf promTypes.file_sd_config) ''
370 List of file service discovery configurations.
371 '';
372
373 gce_sd_configs = mkOpt (types.listOf promTypes.gce_sd_config) ''
374 List of Google Compute Engine service discovery configurations.
375
376 See <link
377 xlink:href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config">the
378 relevant Prometheus configuration docs</link> for more detail.
379 '';
380
381 static_configs = mkOpt (types.listOf promTypes.static_config) ''
382 List of labeled target groups for this job.
383 '';
384
385 relabel_configs = mkOpt (types.listOf promTypes.relabel_config) ''
386 List of relabel configurations.
387 '';
388
389 metric_relabel_configs = mkOpt (types.listOf promTypes.relabel_config) ''
390 List of metric relabel configurations.
391 '';
392
393 sample_limit = mkDefOpt types.int "0" ''
394 Per-scrape limit on number of scraped samples that will be accepted.
395 If more than this number of samples are present after metric relabelling
396 the entire scrape will be treated as failed. 0 means no limit.
397 '';
398 };
399 };
400
401 promTypes.static_config = types.submodule {
402 options = {
403 targets = mkOption {
404 type = types.listOf types.str;
405 description = ''
406 The targets specified by the target group.
407 '';
408 };
409 labels = mkOption {
410 type = types.attrsOf types.str;
411 default = {};
412 description = ''
413 Labels assigned to all metrics scraped from the targets.
414 '';
415 };
416 };
417 };
418
419 promTypes.ec2_sd_config = types.submodule {
420 options = {
421 region = mkOption {
422 type = types.str;
423 description = ''
424 The AWS Region.
425 '';
426 };
427 endpoint = mkOpt types.str ''
428 Custom endpoint to be used.
429 '';
430
431 access_key = mkOpt types.str ''
432 The AWS API key id. If blank, the environment variable
433 <literal>AWS_ACCESS_KEY_ID</literal> is used.
434 '';
435
436 secret_key = mkOpt types.str ''
437 The AWS API key secret. If blank, the environment variable
438 <literal>AWS_SECRET_ACCESS_KEY</literal> is used.
439 '';
440
441 profile = mkOpt types.str ''
442 Named AWS profile used to connect to the API.
443 '';
444
445 role_arn = mkOpt types.str ''
446 AWS Role ARN, an alternative to using AWS API keys.
447 '';
448
449 refresh_interval = mkDefOpt types.str "60s" ''
450 Refresh interval to re-read the instance list.
451 '';
452
453 port = mkDefOpt types.int "80" ''
454 The port to scrape metrics from. If using the public IP
455 address, this must instead be specified in the relabeling
456 rule.
457 '';
458
459 filters = mkOpt (types.listOf promTypes.filter) ''
460 Filters can be used optionally to filter the instance list by other criteria.
461 '';
462 };
463 };
464
465 promTypes.filter = types.submodule {
466 options = {
467 name = mkOption {
468 type = types.str;
469 description = ''
470 See <link xlink:href="https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html">this list</link>
471 for the available filters.
472 '';
473 };
474
475 values = mkOption {
476 type = types.listOf types.str;
477 default = [];
478 description = ''
479 Value of the filter.
480 '';
481 };
482 };
483 };
484
485 promTypes.dns_sd_config = types.submodule {
486 options = {
487 names = mkOption {
488 type = types.listOf types.str;
489 description = ''
490 A list of DNS SRV record names to be queried.
491 '';
492 };
493
494 refresh_interval = mkDefOpt types.str "30s" ''
495 The time after which the provided names are refreshed.
496 '';
497 };
498 };
499
500 promTypes.consul_sd_config = types.submodule {
501 options = {
502 server = mkDefOpt types.str "localhost:8500" ''
503 Consul server to query.
504 '';
505
506 token = mkOpt types.str "Consul token";
507
508 datacenter = mkOpt types.str "Consul datacenter";
509
510 scheme = mkDefOpt types.str "http" "Consul scheme";
511
512 username = mkOpt types.str "Consul username";
513
514 password = mkOpt types.str "Consul password";
515
516 tls_config = mkOpt promTypes.tls_config ''
517 Configures the Consul request's TLS settings.
518 '';
519
520 services = mkOpt (types.listOf types.str) ''
521 A list of services for which targets are retrieved.
522 '';
523
524 tags = mkOpt (types.listOf types.str) ''
525 An optional list of tags used to filter nodes for a given
526 service. Services must contain all tags in the list.
527 '';
528
529 node_meta = mkOpt (types.attrsOf types.str) ''
530 Node metadata used to filter nodes for a given service.
531 '';
532
533 tag_separator = mkDefOpt types.str "," ''
534 The string by which Consul tags are joined into the tag label.
535 '';
536
537 allow_stale = mkOpt types.bool ''
538 Allow stale Consul results
539 (see <link xlink:href="https://www.consul.io/api/index.html#consistency-modes"/>).
540
541 Will reduce load on Consul.
542 '';
543
544 refresh_interval = mkDefOpt types.str "30s" ''
545 The time after which the provided names are refreshed.
546
547 On large setup it might be a good idea to increase this value
548 because the catalog will change all the time.
549 '';
550 };
551 };
552
553 promTypes.file_sd_config = types.submodule {
554 options = {
555 files = mkOption {
556 type = types.listOf types.str;
557 description = ''
558 Patterns for files from which target groups are extracted. Refer
559 to the Prometheus documentation for permitted filename patterns
560 and formats.
561 '';
562 };
563
564 refresh_interval = mkDefOpt types.str "5m" ''
565 Refresh interval to re-read the files.
566 '';
567 };
568 };
569
570 promTypes.gce_sd_config = types.submodule {
571 options = {
572 # Use `mkOption` instead of `mkOpt` for project and zone because they are
573 # required configuration values for `gce_sd_config`.
574 project = mkOption {
575 type = types.str;
576 description = ''
577 The GCP Project.
578 '';
579 };
580
581 zone = mkOption {
582 type = types.str;
583 description = ''
584 The zone of the scrape targets. If you need multiple zones use multiple
585 gce_sd_configs.
586 '';
587 };
588
589 filter = mkOpt types.str ''
590 Filter can be used optionally to filter the instance list by other
591 criteria Syntax of this filter string is described here in the filter
592 query parameter section: <link
593 xlink:href="https://cloud.google.com/compute/docs/reference/latest/instances/list"
594 />.
595 '';
596
597 refresh_interval = mkDefOpt types.str "60s" ''
598 Refresh interval to re-read the cloud instance list.
599 '';
600
601 port = mkDefOpt types.port "80" ''
602 The port to scrape metrics from. If using the public IP address, this
603 must instead be specified in the relabeling rule.
604 '';
605
606 tag_separator = mkDefOpt types.str "," ''
607 The tag separator used to separate concatenated GCE instance network tags.
608
609 See the GCP documentation on network tags for more information: <link
610 xlink:href="https://cloud.google.com/vpc/docs/add-remove-network-tags"
611 />
612 '';
613 };
614 };
615
616 promTypes.relabel_config = types.submodule {
617 options = {
618 source_labels = mkOpt (types.listOf types.str) ''
619 The source labels select values from existing labels. Their content
620 is concatenated using the configured separator and matched against
621 the configured regular expression.
622 '';
623
624 separator = mkDefOpt types.str ";" ''
625 Separator placed between concatenated source label values.
626 '';
627
628 target_label = mkOpt types.str ''
629 Label to which the resulting value is written in a replace action.
630 It is mandatory for replace actions.
631 '';
632
633 regex = mkDefOpt types.str "(.*)" ''
634 Regular expression against which the extracted value is matched.
635 '';
636
637 modulus = mkOpt types.int ''
638 Modulus to take of the hash of the source label values.
639 '';
640
641 replacement = mkDefOpt types.str "$1" ''
642 Replacement value against which a regex replace is performed if the
643 regular expression matches.
644 '';
645
646 action =
647 mkDefOpt (types.enum ["replace" "keep" "drop" "hashmod" "labelmap" "labeldrop" "labelkeep"]) "replace" ''
648 Action to perform based on regex matching.
649 '';
650 };
651 };
652
653 promTypes.tls_config = types.submodule {
654 options = {
655 ca_file = mkOpt types.str ''
656 CA certificate to validate API server certificate with.
657 '';
658
659 cert_file = mkOpt types.str ''
660 Certificate file for client cert authentication to the server.
661 '';
662
663 key_file = mkOpt types.str ''
664 Key file for client cert authentication to the server.
665 '';
666
667 server_name = mkOpt types.str ''
668 ServerName extension to indicate the name of the server.
669 http://tools.ietf.org/html/rfc4366#section-3.1
670 '';
671
672 insecure_skip_verify = mkOpt types.bool ''
673 Disable validation of the server certificate.
674 '';
675 };
676 };
677
678in {
679
680 imports = [
681 (mkRenamedOptionModule [ "services" "prometheus2" ] [ "services" "prometheus" ])
682 ];
683
684 options.services.prometheus = {
685
686 enable = mkOption {
687 type = types.bool;
688 default = false;
689 description = ''
690 Enable the Prometheus monitoring daemon.
691 '';
692 };
693
694 package = mkOption {
695 type = types.package;
696 default = pkgs.prometheus;
697 defaultText = "pkgs.prometheus";
698 description = ''
699 The prometheus package that should be used.
700 '';
701 };
702
703 port = mkOption {
704 type = types.port;
705 default = 9090;
706 description = ''
707 Port to listen on.
708 '';
709 };
710
711 listenAddress = mkOption {
712 type = types.str;
713 default = "0.0.0.0";
714 description = ''
715 Address to listen on for the web interface, API, and telemetry.
716 '';
717 };
718
719 stateDir = mkOption {
720 type = types.str;
721 default = "prometheus2";
722 description = ''
723 Directory below <literal>/var/lib</literal> to store Prometheus metrics data.
724 This directory will be created automatically using systemd's StateDirectory mechanism.
725 '';
726 };
727
728 extraFlags = mkOption {
729 type = types.listOf types.str;
730 default = [];
731 description = ''
732 Extra commandline options when launching Prometheus.
733 '';
734 };
735
736 environmentFile = mkOption {
737 type = types.nullOr types.path;
738 default = null;
739 example = "/root/prometheus.env";
740 description = ''
741 Environment file as defined in <citerefentry>
742 <refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum>
743 </citerefentry>.
744
745 Secrets may be passed to the service without adding them to the
746 world-readable Nix store, by specifying placeholder variables as
747 the option value in Nix and setting these variables accordingly in the
748 environment file.
749
750 Environment variables from this file will be interpolated into the
751 config file using envsubst with this syntax:
752 <literal>$ENVIRONMENT ''${VARIABLE}</literal>
753
754 <programlisting>
755 # Example scrape config entry handling an OAuth bearer token
756 {
757 job_name = "home_assistant";
758 metrics_path = "/api/prometheus";
759 scheme = "https";
760 bearer_token = "\''${HOME_ASSISTANT_BEARER_TOKEN}";
761 [...]
762 }
763 </programlisting>
764
765 <programlisting>
766 # Content of the environment file
767 HOME_ASSISTANT_BEARER_TOKEN=someoauthbearertoken
768 </programlisting>
769
770 Note that this file needs to be available on the host on which
771 <literal>Prometheus</literal> is running.
772 '';
773 };
774
775 configText = mkOption {
776 type = types.nullOr types.lines;
777 default = null;
778 description = ''
779 If non-null, this option defines the text that is written to
780 prometheus.yml. If null, the contents of prometheus.yml is generated
781 from the structured config options.
782 '';
783 };
784
785 globalConfig = mkOption {
786 type = promTypes.globalConfig;
787 default = {};
788 description = ''
789 Parameters that are valid in all configuration contexts. They
790 also serve as defaults for other configuration sections
791 '';
792 };
793
794 remoteRead = mkOption {
795 type = types.listOf promTypes.remote_read;
796 default = [];
797 description = ''
798 Parameters of the endpoints to query from.
799 See <link xlink:href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_read">the official documentation</link> for more information.
800 '';
801 };
802
803 remoteWrite = mkOption {
804 type = types.listOf promTypes.remote_write;
805 default = [];
806 description = ''
807 Parameters of the endpoints to send samples to.
808 See <link xlink:href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write">the official documentation</link> for more information.
809 '';
810 };
811
812 rules = mkOption {
813 type = types.listOf types.str;
814 default = [];
815 description = ''
816 Alerting and/or Recording rules to evaluate at runtime.
817 '';
818 };
819
820 ruleFiles = mkOption {
821 type = types.listOf types.path;
822 default = [];
823 description = ''
824 Any additional rules files to include in this configuration.
825 '';
826 };
827
828 scrapeConfigs = mkOption {
829 type = types.listOf promTypes.scrape_config;
830 default = [];
831 description = ''
832 A list of scrape configurations.
833 '';
834 };
835
836 alertmanagers = mkOption {
837 type = types.listOf types.attrs;
838 example = literalExample ''
839 [ {
840 scheme = "https";
841 path_prefix = "/alertmanager";
842 static_configs = [ {
843 targets = [
844 "prometheus.domain.tld"
845 ];
846 } ];
847 } ]
848 '';
849 default = [];
850 description = ''
851 A list of alertmanagers to send alerts to.
852 See <link xlink:href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alertmanager_config">the official documentation</link> for more information.
853 '';
854 };
855
856 alertmanagerNotificationQueueCapacity = mkOption {
857 type = types.int;
858 default = 10000;
859 description = ''
860 The capacity of the queue for pending alert manager notifications.
861 '';
862 };
863
864 alertmanagerTimeout = mkOption {
865 type = types.int;
866 default = 10;
867 description = ''
868 Alert manager HTTP API timeout (in seconds).
869 '';
870 };
871
872 webExternalUrl = mkOption {
873 type = types.nullOr types.str;
874 default = null;
875 example = "https://example.com/";
876 description = ''
877 The URL under which Prometheus is externally reachable (for example,
878 if Prometheus is served via a reverse proxy).
879 '';
880 };
881
882 checkConfig = mkOption {
883 type = types.bool;
884 default = true;
885 description = ''
886 Check configuration with <literal>promtool
887 check</literal>. The call to <literal>promtool</literal> is
888 subject to sandboxing by Nix. When credentials are stored in
889 external files (<literal>password_file</literal>,
890 <literal>bearer_token_file</literal>, etc), they will not be
891 visible to <literal>promtool</literal> and it will report
892 errors, despite a correct configuration.
893 '';
894 };
895
896 retentionTime = mkOption {
897 type = types.nullOr types.str;
898 default = null;
899 example = "15d";
900 description = ''
901 How long to retain samples in storage.
902 '';
903 };
904 };
905
906 config = mkIf cfg.enable {
907 assertions = [
908 ( let
909 # Match something with dots (an IPv4 address) or something ending in
910 # a square bracket (an IPv6 addresses) followed by a port number.
911 legacy = builtins.match "(.*\\..*|.*]):([[:digit:]]+)" cfg.listenAddress;
912 in {
913 assertion = legacy == null;
914 message = ''
915 Do not specify the port for Prometheus to listen on in the
916 listenAddress option; use the port option instead:
917 services.prometheus.listenAddress = ${builtins.elemAt legacy 0};
918 services.prometheus.port = ${builtins.elemAt legacy 1};
919 '';
920 }
921 )
922 ];
923
924 users.groups.prometheus.gid = config.ids.gids.prometheus;
925 users.users.prometheus = {
926 description = "Prometheus daemon user";
927 uid = config.ids.uids.prometheus;
928 group = "prometheus";
929 };
930 systemd.services.prometheus = {
931 wantedBy = [ "multi-user.target" ];
932 after = [ "network.target" ];
933 preStart = ''
934 ${lib.getBin pkgs.envsubst}/bin/envsubst -o "/run/prometheus/prometheus-substituted.yaml" \
935 -i "${prometheusYml}"
936 '';
937 serviceConfig = {
938 ExecStart = "${cfg.package}/bin/prometheus" +
939 optionalString (length cmdlineArgs != 0) (" \\\n " +
940 concatStringsSep " \\\n " cmdlineArgs);
941 User = "prometheus";
942 Restart = "always";
943 EnvironmentFile = mkIf (cfg.environmentFile != null) [ cfg.environmentFile ];
944 RuntimeDirectory = "prometheus";
945 RuntimeDirectoryMode = "0700";
946 WorkingDirectory = workingDir;
947 StateDirectory = cfg.stateDir;
948 };
949 };
950 };
951}