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