at 25.11-pre 30 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8let 9 inherit (lib) 10 collect 11 concatLists 12 concatStringsSep 13 flip 14 getAttrFromPath 15 hasPrefix 16 isList 17 length 18 literalExpression 19 literalMD 20 mapAttrsRecursiveCond 21 mapAttrsToList 22 mkEnableOption 23 mkIf 24 mkMerge 25 mkOption 26 mkPackageOption 27 optional 28 optionalAttrs 29 optionalString 30 types 31 ; 32 33 cfg = config.services.thanos; 34 35 nullOpt = 36 type: description: 37 mkOption { 38 type = if type.check null then type else types.nullOr type; 39 default = null; 40 description = description; 41 }; 42 43 optionToArgs = opt: v: optional (v != null) ''--${opt}="${toString v}"''; 44 flagToArgs = opt: v: optional v "--${opt}"; 45 listToArgs = opt: vs: map (v: ''--${opt}="${v}"'') vs; 46 attrsToArgs = opt: kvs: mapAttrsToList (k: v: ''--${opt}=${k}=\"${v}\"'') kvs; 47 48 mkParamDef = 49 type: default: description: 50 mkParam type ( 51 description 52 + '' 53 54 Defaults to `${toString default}` in Thanos 55 when set to `null`. 56 '' 57 ); 58 59 mkParam = type: description: { 60 toArgs = optionToArgs; 61 option = nullOpt type description; 62 }; 63 64 mkFlagParam = description: { 65 toArgs = flagToArgs; 66 option = mkOption { 67 type = types.bool; 68 default = false; 69 description = description; 70 }; 71 }; 72 73 mkListParam = opt: description: { 74 toArgs = _opt: listToArgs opt; 75 option = mkOption { 76 type = types.listOf types.str; 77 default = [ ]; 78 description = description; 79 }; 80 }; 81 82 mkAttrsParam = opt: description: { 83 toArgs = _opt: attrsToArgs opt; 84 option = mkOption { 85 type = types.attrsOf types.str; 86 default = { }; 87 description = description; 88 }; 89 }; 90 91 mkStateDirParam = opt: default: description: { 92 toArgs = _opt: stateDir: optionToArgs opt "/var/lib/${stateDir}"; 93 option = mkOption { 94 type = types.str; 95 inherit default; 96 description = description; 97 }; 98 }; 99 100 format = pkgs.formats.yaml { }; 101 102 thanos = 103 cmd: 104 "${cfg.package}/bin/thanos ${cmd}" 105 + ( 106 let 107 args = cfg.${cmd}.arguments; 108 in 109 optionalString (length args != 0) (" \\\n " + concatStringsSep " \\\n " args) 110 ); 111 112 argumentsOf = 113 cmd: 114 concatLists ( 115 collect isList ( 116 flip mapParamsRecursive params.${cmd} ( 117 path: param: 118 let 119 opt = concatStringsSep "." path; 120 v = getAttrFromPath path cfg.${cmd}; 121 in 122 param.toArgs opt v 123 ) 124 ) 125 ); 126 127 mkArgumentsOption = 128 cmd: 129 mkOption { 130 type = types.listOf types.str; 131 default = argumentsOf cmd; 132 defaultText = literalMD '' 133 calculated from `config.services.thanos.${cmd}` 134 ''; 135 description = '' 136 Arguments to the `thanos ${cmd}` command. 137 138 Defaults to a list of arguments formed by converting the structured 139 options of {option}`services.thanos.${cmd}` to a list of arguments. 140 141 Overriding this option will cause none of the structured options to have 142 any effect. So only set this if you know what you're doing! 143 ''; 144 }; 145 146 mapParamsRecursive = 147 let 148 noParam = attr: !(attr ? toArgs && attr ? option); 149 in 150 mapAttrsRecursiveCond noParam; 151 152 paramsToOptions = mapParamsRecursive (_path: param: param.option); 153 154 params = { 155 156 log = { 157 158 log.level = 159 mkParamDef 160 (types.enum [ 161 "debug" 162 "info" 163 "warn" 164 "error" 165 "fatal" 166 ]) 167 "info" 168 '' 169 Log filtering level. 170 ''; 171 172 log.format = mkParam types.str '' 173 Log format to use. 174 ''; 175 }; 176 177 tracing = cfg: { 178 tracing.config-file = { 179 toArgs = _opt: path: optionToArgs "tracing.config-file" path; 180 option = mkOption { 181 type = with types; nullOr str; 182 default = 183 if cfg.tracing.config == null then 184 null 185 else 186 toString (format.generate "tracing.yaml" cfg.tracing.config); 187 defaultText = literalExpression '' 188 if config.services.thanos.<cmd>.tracing.config == null then null 189 else toString (format.generate "tracing.yaml" config.services.thanos.<cmd>.tracing.config); 190 ''; 191 description = '' 192 Path to YAML file that contains tracing configuration. 193 194 See format details: <https://thanos.io/tip/thanos/tracing.md/#configuration> 195 ''; 196 }; 197 }; 198 199 tracing.config = { 200 toArgs = _opt: _attrs: [ ]; 201 option = nullOpt format.type '' 202 Tracing configuration. 203 204 When not `null` the attribute set gets converted to 205 a YAML file and stored in the Nix store. The option 206 {option}`tracing.config-file` will default to its path. 207 208 If {option}`tracing.config-file` is set this option has no effect. 209 210 See format details: <https://thanos.io/tip/thanos/tracing.md/#configuration> 211 ''; 212 }; 213 }; 214 215 common = 216 cfg: 217 params.log 218 // params.tracing cfg 219 // { 220 221 http-address = mkParamDef types.str "0.0.0.0:10902" '' 222 Listen `host:port` for HTTP endpoints. 223 ''; 224 225 grpc-address = mkParamDef types.str "0.0.0.0:10901" '' 226 Listen `ip:port` address for gRPC endpoints (StoreAPI). 227 228 Make sure this address is routable from other components. 229 ''; 230 231 grpc-server-tls-cert = mkParam types.str '' 232 TLS Certificate for gRPC server, leave blank to disable TLS 233 ''; 234 235 grpc-server-tls-key = mkParam types.str '' 236 TLS Key for the gRPC server, leave blank to disable TLS 237 ''; 238 239 grpc-server-tls-client-ca = mkParam types.str '' 240 TLS CA to verify clients against. 241 242 If no client CA is specified, there is no client verification on server side. 243 (tls.NoClientCert) 244 ''; 245 }; 246 247 objstore = cfg: { 248 249 objstore.config-file = { 250 toArgs = _opt: path: optionToArgs "objstore.config-file" path; 251 option = mkOption { 252 type = with types; nullOr str; 253 default = 254 if cfg.objstore.config == null then 255 null 256 else 257 toString (format.generate "objstore.yaml" cfg.objstore.config); 258 defaultText = literalExpression '' 259 if config.services.thanos.<cmd>.objstore.config == null then null 260 else toString (format.generate "objstore.yaml" config.services.thanos.<cmd>.objstore.config); 261 ''; 262 description = '' 263 Path to YAML file that contains object store configuration. 264 265 See format details: <https://thanos.io/tip/thanos/storage.md/#configuring-access-to-object-storage> 266 ''; 267 }; 268 }; 269 270 objstore.config = { 271 toArgs = _opt: _attrs: [ ]; 272 option = nullOpt format.type '' 273 Object store configuration. 274 275 When not `null` the attribute set gets converted to 276 a YAML file and stored in the Nix store. The option 277 {option}`objstore.config-file` will default to its path. 278 279 If {option}`objstore.config-file` is set this option has no effect. 280 281 See format details: <https://thanos.io/tip/thanos/storage.md/#configuring-access-to-object-storage> 282 ''; 283 }; 284 }; 285 286 sidecar = 287 params.common cfg.sidecar 288 // params.objstore cfg.sidecar 289 // { 290 291 prometheus.url = mkParamDef types.str "http://localhost:9090" '' 292 URL at which to reach Prometheus's API. 293 294 For better performance use local network. 295 ''; 296 297 tsdb.path = { 298 toArgs = optionToArgs; 299 option = mkOption { 300 type = types.str; 301 default = "/var/lib/${config.services.prometheus.stateDir}/data"; 302 defaultText = literalExpression ''"/var/lib/''${config.services.prometheus.stateDir}/data"''; 303 description = '' 304 Data directory of TSDB. 305 ''; 306 }; 307 }; 308 309 reloader.config-file = mkParam types.str '' 310 Config file watched by the reloader. 311 ''; 312 313 reloader.config-envsubst-file = mkParam types.str '' 314 Output file for environment variable substituted config file. 315 ''; 316 317 reloader.rule-dirs = mkListParam "reloader.rule-dir" '' 318 Rule directories for the reloader to refresh. 319 ''; 320 321 }; 322 323 store = 324 params.common cfg.store 325 // params.objstore cfg.store 326 // { 327 328 stateDir = mkStateDirParam "data-dir" "thanos-store" '' 329 Data directory relative to `/var/lib` 330 in which to cache remote blocks. 331 ''; 332 333 index-cache-size = mkParamDef types.str "250MB" '' 334 Maximum size of items held in the index cache. 335 ''; 336 337 chunk-pool-size = mkParamDef types.str "2GB" '' 338 Maximum size of concurrently allocatable bytes for chunks. 339 ''; 340 341 store.limits.request-samples = mkParamDef types.int 0 '' 342 The maximum samples allowed for a single Series request. 343 The Series call fails if this limit is exceeded. 344 345 `0` means no limit. 346 347 NOTE: For efficiency the limit is internally implemented as 'chunks limit' 348 considering each chunk contains a maximum of 120 samples. 349 ''; 350 351 store.grpc.series-max-concurrency = mkParamDef types.int 20 '' 352 Maximum number of concurrent Series calls. 353 ''; 354 355 sync-block-duration = mkParamDef types.str "3m" '' 356 Repeat interval for syncing the blocks between local and remote view. 357 ''; 358 359 block-sync-concurrency = mkParamDef types.int 20 '' 360 Number of goroutines to use when syncing blocks from object storage. 361 ''; 362 363 min-time = mkParamDef types.str "0000-01-01T00:00:00Z" '' 364 Start of time range limit to serve. 365 366 Thanos Store serves only metrics, which happened later than this 367 value. Option can be a constant time in RFC3339 format or time duration 368 relative to current time, such as -1d or 2h45m. Valid duration units are 369 ms, s, m, h, d, w, y. 370 ''; 371 372 max-time = mkParamDef types.str "9999-12-31T23:59:59Z" '' 373 End of time range limit to serve. 374 375 Thanos Store serves only blocks, which happened earlier than this 376 value. Option can be a constant time in RFC3339 format or time duration 377 relative to current time, such as -1d or 2h45m. Valid duration units are 378 ms, s, m, h, d, w, y. 379 ''; 380 }; 381 382 query = params.common cfg.query // { 383 384 grpc-client-tls-secure = mkFlagParam '' 385 Use TLS when talking to the gRPC server 386 ''; 387 388 grpc-client-tls-cert = mkParam types.str '' 389 TLS Certificates to use to identify this client to the server 390 ''; 391 392 grpc-client-tls-key = mkParam types.str '' 393 TLS Key for the client's certificate 394 ''; 395 396 grpc-client-tls-ca = mkParam types.str '' 397 TLS CA Certificates to use to verify gRPC servers 398 ''; 399 400 grpc-client-server-name = mkParam types.str '' 401 Server name to verify the hostname on the returned gRPC certificates. 402 See <https://tools.ietf.org/html/rfc4366#section-3.1> 403 ''; 404 405 grpc-compression = mkParam types.str '' 406 Compression algorithm to use for gRPC requests to other clients. 407 ''; 408 409 web.route-prefix = mkParam types.str '' 410 Prefix for API and UI endpoints. 411 412 This allows thanos UI to be served on a sub-path. This option is 413 analogous to {option}`web.route-prefix` of Promethus. 414 ''; 415 416 web.external-prefix = mkParam types.str '' 417 Static prefix for all HTML links and redirect URLs in the UI query web 418 interface. 419 420 Actual endpoints are still served on / or the 421 {option}`web.route-prefix`. This allows thanos UI to be served 422 behind a reverse proxy that strips a URL sub-path. 423 ''; 424 425 web.prefix-header = mkParam types.str '' 426 Name of HTTP request header used for dynamic prefixing of UI links and 427 redirects. 428 429 This option is ignored if the option 430 `web.external-prefix` is set. 431 432 Security risk: enable this option only if a reverse proxy in front of 433 thanos is resetting the header. 434 435 The setting `web.prefix-header="X-Forwarded-Prefix"` 436 can be useful, for example, if Thanos UI is served via Traefik reverse 437 proxy with `PathPrefixStrip` option enabled, which 438 sends the stripped prefix value in `X-Forwarded-Prefix` 439 header. This allows thanos UI to be served on a sub-path. 440 ''; 441 442 query.timeout = mkParamDef types.str "2m" '' 443 Maximum time to process query by query node. 444 ''; 445 446 query.max-concurrent = mkParamDef types.int 20 '' 447 Maximum number of queries processed concurrently by query node. 448 ''; 449 450 query.replica-labels = mkListParam "query.replica-label" '' 451 Labels to treat as a replica indicator along which data is 452 deduplicated. 453 454 Still you will be able to query without deduplication using 455 'dedup=false' parameter. Data includes time series, recording 456 rules, and alerting rules. 457 ''; 458 459 selector-labels = mkAttrsParam "selector-label" '' 460 Query selector labels that will be exposed in info endpoint. 461 ''; 462 463 endpoints = mkListParam "endpoint" '' 464 Addresses of statically configured Thanos API servers (repeatable). 465 466 The scheme may be prefixed with 'dns+' or 'dnssrv+' to detect 467 Thanos API servers through respective DNS lookups. 468 ''; 469 470 store.sd-files = mkListParam "store.sd-files" '' 471 Path to files that contain addresses of store API servers. The path 472 can be a glob pattern. 473 ''; 474 475 store.sd-interval = mkParamDef types.str "5m" '' 476 Refresh interval to re-read file SD files. It is used as a resync fallback. 477 ''; 478 479 store.sd-dns-interval = mkParamDef types.str "30s" '' 480 Interval between DNS resolutions. 481 ''; 482 483 store.unhealthy-timeout = mkParamDef types.str "5m" '' 484 Timeout before an unhealthy store is cleaned from the store UI page. 485 ''; 486 487 query.auto-downsampling = mkFlagParam '' 488 Enable automatic adjustment (step / 5) to what source of data should 489 be used in store gateways if no 490 `max_source_resolution` param is specified. 491 ''; 492 493 query.partial-response = mkFlagParam '' 494 Enable partial response for queries if no 495 `partial_response` param is specified. 496 ''; 497 498 query.default-evaluation-interval = mkParamDef types.str "1m" '' 499 Set default evaluation interval for sub queries. 500 ''; 501 502 store.response-timeout = mkParamDef types.str "0ms" '' 503 If a Store doesn't send any data in this specified duration then a 504 Store will be ignored and partial data will be returned if it's 505 enabled. `0` disables timeout. 506 ''; 507 }; 508 509 query-frontend = params.common cfg.query-frontend // { 510 query-frontend.downstream-url = mkParamDef types.str "http://localhost:9090" '' 511 URL of downstream Prometheus Query compatible API. 512 ''; 513 }; 514 515 rule = 516 params.common cfg.rule 517 // params.objstore cfg.rule 518 // { 519 520 labels = mkAttrsParam "label" '' 521 Labels to be applied to all generated metrics. 522 523 Similar to external labels for Prometheus, 524 used to identify ruler and its blocks as unique source. 525 ''; 526 527 stateDir = mkStateDirParam "data-dir" "thanos-rule" '' 528 Data directory relative to `/var/lib`. 529 ''; 530 531 rule-files = mkListParam "rule-file" '' 532 Rule files that should be used by rule manager. Can be in glob format. 533 ''; 534 535 eval-interval = mkParamDef types.str "1m" '' 536 The default evaluation interval to use. 537 ''; 538 539 tsdb.block-duration = mkParamDef types.str "2h" '' 540 Block duration for TSDB block. 541 ''; 542 543 tsdb.retention = mkParamDef types.str "48h" '' 544 Block retention time on local disk. 545 ''; 546 547 alertmanagers.urls = mkListParam "alertmanagers.url" '' 548 Alertmanager replica URLs to push firing alerts. 549 550 Ruler claims success if push to at least one alertmanager from 551 discovered succeeds. The scheme may be prefixed with 552 `dns+` or `dnssrv+` to detect 553 Alertmanager IPs through respective DNS lookups. The port defaults to 554 `9093` or the SRV record's value. The URL path is 555 used as a prefix for the regular Alertmanager API path. 556 ''; 557 558 alertmanagers.send-timeout = mkParamDef types.str "10s" '' 559 Timeout for sending alerts to alertmanager. 560 ''; 561 562 alert.query-url = mkParam types.str '' 563 The external Thanos Query URL that would be set in all alerts 'Source' field. 564 ''; 565 566 alert.label-drop = mkListParam "alert.label-drop" '' 567 Labels by name to drop before sending to alertmanager. 568 569 This allows alert to be deduplicated on replica label. 570 571 Similar Prometheus alert relabelling 572 ''; 573 574 web.route-prefix = mkParam types.str '' 575 Prefix for API and UI endpoints. 576 577 This allows thanos UI to be served on a sub-path. 578 579 This option is analogous to `--web.route-prefix` of Promethus. 580 ''; 581 582 web.external-prefix = mkParam types.str '' 583 Static prefix for all HTML links and redirect URLs in the UI query web 584 interface. 585 586 Actual endpoints are still served on / or the 587 {option}`web.route-prefix`. This allows thanos UI to be served 588 behind a reverse proxy that strips a URL sub-path. 589 ''; 590 591 web.prefix-header = mkParam types.str '' 592 Name of HTTP request header used for dynamic prefixing of UI links and 593 redirects. 594 595 This option is ignored if the option 596 {option}`web.external-prefix` is set. 597 598 Security risk: enable this option only if a reverse proxy in front of 599 thanos is resetting the header. 600 601 The header `X-Forwarded-Prefix` can be useful, for 602 example, if Thanos UI is served via Traefik reverse proxy with 603 `PathPrefixStrip` option enabled, which sends the 604 stripped prefix value in `X-Forwarded-Prefix` 605 header. This allows thanos UI to be served on a sub-path. 606 ''; 607 608 query.addresses = mkListParam "query" '' 609 Addresses of statically configured query API servers. 610 611 The scheme may be prefixed with `dns+` or 612 `dnssrv+` to detect query API servers through 613 respective DNS lookups. 614 ''; 615 616 query.sd-files = mkListParam "query.sd-files" '' 617 Path to file that contain addresses of query peers. 618 The path can be a glob pattern. 619 ''; 620 621 query.sd-interval = mkParamDef types.str "5m" '' 622 Refresh interval to re-read file SD files. (used as a fallback) 623 ''; 624 625 query.sd-dns-interval = mkParamDef types.str "30s" '' 626 Interval between DNS resolutions. 627 ''; 628 }; 629 630 compact = 631 params.log 632 // params.tracing cfg.compact 633 // params.objstore cfg.compact 634 // { 635 636 http-address = mkParamDef types.str "0.0.0.0:10902" '' 637 Listen `host:port` for HTTP endpoints. 638 ''; 639 640 stateDir = mkStateDirParam "data-dir" "thanos-compact" '' 641 Data directory relative to `/var/lib` 642 in which to cache blocks and process compactions. 643 ''; 644 645 consistency-delay = mkParamDef types.str "30m" '' 646 Minimum age of fresh (non-compacted) blocks before they are being 647 processed. Malformed blocks older than the maximum of consistency-delay 648 and 30m0s will be removed. 649 ''; 650 651 retention.resolution-raw = mkParamDef types.str "0d" '' 652 How long to retain raw samples in bucket. 653 654 `0d` - disables this retention 655 ''; 656 657 retention.resolution-5m = mkParamDef types.str "0d" '' 658 How long to retain samples of resolution 1 (5 minutes) in bucket. 659 660 `0d` - disables this retention 661 ''; 662 663 retention.resolution-1h = mkParamDef types.str "0d" '' 664 How long to retain samples of resolution 2 (1 hour) in bucket. 665 666 `0d` - disables this retention 667 ''; 668 669 startAt = { 670 toArgs = _opt: startAt: flagToArgs "wait" (startAt == null); 671 option = nullOpt types.str '' 672 When this option is set to a `systemd.time` 673 specification the Thanos compactor will run at the specified period. 674 675 When this option is `null` the Thanos compactor service 676 will run continuously. So it will not exit after all compactions have 677 been processed but wait for new work. 678 ''; 679 }; 680 681 downsampling.disable = mkFlagParam '' 682 Disables downsampling. 683 684 This is not recommended as querying long time ranges without 685 non-downsampled data is not efficient and useful e.g it is not possible 686 to render all samples for a human eye anyway 687 ''; 688 689 compact.concurrency = mkParamDef types.int 1 '' 690 Number of goroutines to use when compacting groups. 691 ''; 692 }; 693 694 downsample = 695 params.log 696 // params.tracing cfg.downsample 697 // params.objstore cfg.downsample 698 // { 699 700 stateDir = mkStateDirParam "data-dir" "thanos-downsample" '' 701 Data directory relative to `/var/lib` 702 in which to cache blocks and process downsamplings. 703 ''; 704 705 }; 706 707 receive = 708 params.common cfg.receive 709 // params.objstore cfg.receive 710 // { 711 712 receive.grpc-compression = mkParam types.str '' 713 Compression algorithm to use for gRPC requests to other receivers. 714 ''; 715 716 remote-write.address = mkParamDef types.str "0.0.0.0:19291" '' 717 Address to listen on for remote write requests. 718 ''; 719 720 stateDir = mkStateDirParam "tsdb.path" "thanos-receive" '' 721 Data directory relative to `/var/lib` of TSDB. 722 ''; 723 724 labels = mkAttrsParam "label" '' 725 External labels to announce. 726 727 This flag will be removed in the future when handling multiple tsdb 728 instances is added. 729 ''; 730 731 tsdb.retention = mkParamDef types.str "15d" '' 732 How long to retain raw samples on local storage. 733 734 `0d` - disables this retention 735 ''; 736 }; 737 738 }; 739 740 assertRelativeStateDir = cmd: { 741 assertions = [ 742 { 743 assertion = !hasPrefix "/" cfg.${cmd}.stateDir; 744 message = 745 "The option services.thanos.${cmd}.stateDir should not be an absolute directory." 746 + " It should be a directory relative to /var/lib."; 747 } 748 ]; 749 }; 750 751in 752{ 753 754 options.services.thanos = { 755 756 package = mkPackageOption pkgs "thanos" { }; 757 758 sidecar = paramsToOptions params.sidecar // { 759 enable = mkEnableOption "the Thanos sidecar for Prometheus server"; 760 arguments = mkArgumentsOption "sidecar"; 761 }; 762 763 store = paramsToOptions params.store // { 764 enable = mkEnableOption "the Thanos store node giving access to blocks in a bucket provider"; 765 arguments = mkArgumentsOption "store"; 766 }; 767 768 query = paramsToOptions params.query // { 769 enable = mkEnableOption ( 770 "the Thanos query node exposing PromQL enabled Query API " 771 + "with data retrieved from multiple store nodes" 772 ); 773 arguments = mkArgumentsOption "query"; 774 }; 775 776 query-frontend = paramsToOptions params.query-frontend // { 777 enable = mkEnableOption ( 778 "the Thanos query frontend implements a service deployed in front of queriers to 779 improve query parallelization and caching." 780 ); 781 arguments = mkArgumentsOption "query-frontend"; 782 }; 783 784 rule = paramsToOptions params.rule // { 785 enable = mkEnableOption ( 786 "the Thanos ruler service which evaluates Prometheus rules against" 787 + " given Query nodes, exposing Store API and storing old blocks in bucket" 788 ); 789 arguments = mkArgumentsOption "rule"; 790 }; 791 792 compact = paramsToOptions params.compact // { 793 enable = mkEnableOption "the Thanos compactor which continuously compacts blocks in an object store bucket"; 794 arguments = mkArgumentsOption "compact"; 795 }; 796 797 downsample = paramsToOptions params.downsample // { 798 enable = mkEnableOption "the Thanos downsampler which continuously downsamples blocks in an object store bucket"; 799 arguments = mkArgumentsOption "downsample"; 800 }; 801 802 receive = paramsToOptions params.receive // { 803 enable = mkEnableOption ( 804 "the Thanos receiver which accept Prometheus remote write API requests and write to local tsdb" 805 ); 806 arguments = mkArgumentsOption "receive"; 807 }; 808 }; 809 810 config = mkMerge [ 811 812 (mkIf cfg.sidecar.enable { 813 assertions = [ 814 { 815 assertion = config.services.prometheus.enable; 816 message = "Please enable services.prometheus when enabling services.thanos.sidecar."; 817 } 818 { 819 assertion = 820 !( 821 config.services.prometheus.globalConfig.external_labels == null 822 || config.services.prometheus.globalConfig.external_labels == { } 823 ); 824 message = 825 "services.thanos.sidecar requires uniquely identifying external labels " 826 + "to be configured in the Prometheus server. " 827 + "Please set services.prometheus.globalConfig.external_labels."; 828 } 829 ]; 830 systemd.services.thanos-sidecar = { 831 wantedBy = [ "multi-user.target" ]; 832 after = [ 833 "network.target" 834 "prometheus.service" 835 ]; 836 serviceConfig = { 837 User = "prometheus"; 838 Restart = "always"; 839 ExecStart = thanos "sidecar"; 840 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 841 }; 842 }; 843 }) 844 845 (mkIf cfg.store.enable (mkMerge [ 846 (assertRelativeStateDir "store") 847 { 848 systemd.services.thanos-store = { 849 wantedBy = [ "multi-user.target" ]; 850 after = [ "network.target" ]; 851 serviceConfig = { 852 DynamicUser = true; 853 StateDirectory = cfg.store.stateDir; 854 Restart = "always"; 855 ExecStart = thanos "store"; 856 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 857 }; 858 }; 859 } 860 ])) 861 862 (mkIf cfg.query.enable { 863 systemd.services.thanos-query = { 864 wantedBy = [ "multi-user.target" ]; 865 after = [ "network.target" ]; 866 serviceConfig = { 867 DynamicUser = true; 868 Restart = "always"; 869 ExecStart = thanos "query"; 870 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 871 }; 872 }; 873 }) 874 875 (mkIf cfg.query-frontend.enable { 876 systemd.services.thanos-query-frontend = { 877 wantedBy = [ "multi-user.target" ]; 878 after = [ "network.target" ]; 879 serviceConfig = { 880 DynamicUser = true; 881 Restart = "always"; 882 ExecStart = thanos "query-frontend"; 883 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 884 }; 885 }; 886 }) 887 888 (mkIf cfg.rule.enable (mkMerge [ 889 (assertRelativeStateDir "rule") 890 { 891 systemd.services.thanos-rule = { 892 wantedBy = [ "multi-user.target" ]; 893 after = [ "network.target" ]; 894 serviceConfig = { 895 DynamicUser = true; 896 StateDirectory = cfg.rule.stateDir; 897 Restart = "always"; 898 ExecStart = thanos "rule"; 899 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 900 }; 901 }; 902 } 903 ])) 904 905 (mkIf cfg.compact.enable (mkMerge [ 906 (assertRelativeStateDir "compact") 907 { 908 systemd.services.thanos-compact = 909 let 910 wait = cfg.compact.startAt == null; 911 in 912 { 913 wantedBy = [ "multi-user.target" ]; 914 after = [ "network.target" ]; 915 serviceConfig = { 916 Type = if wait then "simple" else "oneshot"; 917 Restart = if wait then "always" else "no"; 918 DynamicUser = true; 919 StateDirectory = cfg.compact.stateDir; 920 ExecStart = thanos "compact"; 921 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 922 }; 923 } 924 // optionalAttrs (!wait) { inherit (cfg.compact) startAt; }; 925 } 926 ])) 927 928 (mkIf cfg.downsample.enable (mkMerge [ 929 (assertRelativeStateDir "downsample") 930 { 931 systemd.services.thanos-downsample = { 932 wantedBy = [ "multi-user.target" ]; 933 after = [ "network.target" ]; 934 serviceConfig = { 935 DynamicUser = true; 936 StateDirectory = cfg.downsample.stateDir; 937 Restart = "always"; 938 ExecStart = thanos "downsample"; 939 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 940 }; 941 }; 942 } 943 ])) 944 945 (mkIf cfg.receive.enable (mkMerge [ 946 (assertRelativeStateDir "receive") 947 { 948 systemd.services.thanos-receive = { 949 wantedBy = [ "multi-user.target" ]; 950 after = [ "network.target" ]; 951 serviceConfig = { 952 DynamicUser = true; 953 StateDirectory = cfg.receive.stateDir; 954 Restart = "always"; 955 ExecStart = thanos "receive"; 956 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 957 }; 958 }; 959 } 960 ])) 961 962 ]; 963}