From b5ec7fd0fa467e59aa108329315d72642378b13d Mon Sep 17 00:00:00 2001 From: cinereal Date: Fri, 29 May 2026 11:04:55 +0200 Subject: [PATCH] nixos/prometheus-elasticsearch-exporter: init Add a `services.prometheus.exporters.elasticsearch` module wrapping `pkgs.prometheus-elasticsearch-exporter`, which also supports OpenSearch. Credentials are kept out of the process arguments and the store via an `environmentFile` carrying `ES_USERNAME`/`ES_PASSWORD` or `ES_API_KEY`, which override any auth embedded in `--es.uri`. Collector toggles go through the framework's `extraFlags`. A NixOS test exercises the exporter against a single-node OpenSearch instance. Assisted-by: claude-code: claude-opus-4-8 (cherry picked from commit 7195e583ce61da209431d542eeac577ea40ec43e) --- .../monitoring/prometheus/exporters.nix | 1 + .../prometheus/exporters/elasticsearch.nix | 62 +++++++++++++++++++ nixos/tests/prometheus-exporters.nix | 24 +++++++ .../package.nix | 3 + 4 files changed, 90 insertions(+) create mode 100644 nixos/modules/services/monitoring/prometheus/exporters/elasticsearch.nix diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix index d0a667121607..b0a5b92ace6c 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters.nix @@ -62,6 +62,7 @@ let "domain" "dovecot" "ebpf" + "elasticsearch" "fail2ban" "fastly" "flow" diff --git a/nixos/modules/services/monitoring/prometheus/exporters/elasticsearch.nix b/nixos/modules/services/monitoring/prometheus/exporters/elasticsearch.nix new file mode 100644 index 000000000000..1fec5c8d2c59 --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/exporters/elasticsearch.nix @@ -0,0 +1,62 @@ +{ + config, + lib, + pkgs, + utils, + ... +}: + +let + inherit (lib) + mkIf + mkOption + types + ; + + inherit (utils) escapeSystemdExecArgs; + + cfg = config.services.prometheus.exporters.elasticsearch; +in +{ + port = 9114; + extraOpts = { + package = lib.mkPackageOption pkgs "prometheus-elasticsearch-exporter" { }; + + url = mkOption { + type = types.str; + default = "http://localhost:9200"; + example = "https://localhost:9200"; + description = '' + URI of the Elasticsearch (or OpenSearch) node to scrape, passed as + `--es.uri`. Any credentials embedded here are overridden by the + `ES_USERNAME`/`ES_PASSWORD` or `ES_API_KEY` environment variables when + {option}`environmentFile` is set. + ''; + }; + + environmentFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/run/secrets/elasticsearch-exporter.env"; + description = '' + Path to an environment file, as defined in {manpage}`systemd.exec(5)`, + used to pass credentials to the exporter without exposing them in the + process arguments. It should contain either `ES_USERNAME` and + `ES_PASSWORD`, or `ES_API_KEY`. + ''; + }; + }; + serviceOpts = { + serviceConfig = { + EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile; + ExecStart = escapeSystemdExecArgs ( + [ + (lib.getExe cfg.package) + "--web.listen-address=${cfg.listenAddress}:${toString cfg.port}" + "--es.uri=${cfg.url}" + ] + ++ cfg.extraFlags + ); + }; + }; +} diff --git a/nixos/tests/prometheus-exporters.nix b/nixos/tests/prometheus-exporters.nix index 7b088dc85abd..ae2457265047 100644 --- a/nixos/tests/prometheus-exporters.nix +++ b/nixos/tests/prometheus-exporters.nix @@ -436,6 +436,30 @@ let ''; }; + elasticsearch = + { ... }: + { + exporterConfig = { + enable = true; + url = "http://localhost:9200"; + }; + metricProvider = { + # `services.elasticsearch` is unmaintained; OpenSearch is the same + # engine class and is explicitly supported by the exporter. + services.opensearch.enable = true; + virtualisation.memorySize = 2048; + }; + exporterTest = '' + wait_for_unit("opensearch.service") + wait_for_open_port(9200) + wait_for_unit("prometheus-elasticsearch-exporter.service") + wait_for_open_port(9114) + succeed( + "curl -sSf localhost:9114/metrics | grep 'elasticsearch_cluster_health_status'" + ) + ''; + }; + fail2ban = { ... }: { diff --git a/pkgs/by-name/pr/prometheus-elasticsearch-exporter/package.nix b/pkgs/by-name/pr/prometheus-elasticsearch-exporter/package.nix index c8f5ab01800e..17d5856e6906 100644 --- a/pkgs/by-name/pr/prometheus-elasticsearch-exporter/package.nix +++ b/pkgs/by-name/pr/prometheus-elasticsearch-exporter/package.nix @@ -2,6 +2,7 @@ lib, buildGoModule, fetchFromGitHub, + nixosTests, }: buildGoModule (finalAttrs: { pname = "elasticsearch_exporter"; @@ -16,6 +17,8 @@ buildGoModule (finalAttrs: { vendorHash = "sha256-8y0M1b34eJpuHOuXPemhB5kKwBSgU7cMFxOaIZFS/bo="; + passthru.tests = { inherit (nixosTests.prometheus-exporters) elasticsearch; }; + meta = { description = "Elasticsearch stats exporter for Prometheus"; mainProgram = "elasticsearch_exporter";