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