0
0
Fork 0
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-07-13 13:40:28 +03:00

treewide: format all inactive Nix files

After final improvements to the official formatter implementation,
this commit now performs the first treewide reformat of Nix files using it.
This is part of the implementation of RFC 166.

Only "inactive" files are reformatted, meaning only files that
aren't being touched by any PR with activity in the past 2 months.
This is to avoid conflicts for PRs that might soon be merged.
Later we can do a full treewide reformat to get the rest,
which should not cause as many conflicts.

A CI check has already been running for some time to ensure that new and
already-formatted files are formatted, so the files being reformatted here
should also stay formatted.

This commit was automatically created and can be verified using

    nix-build https://github.com/infinisil/treewide-nixpkgs-reformat-script/archive/a08b3a4d199c6124ac5b36a889d9099b4383463f.tar.gz \
      --argstr baseRev b32a094368
    result/bin/apply-formatting $NIXPKGS_PATH
This commit is contained in:
Silvan Mosberger 2024-12-10 20:26:33 +01:00
parent b32a094368
commit 4f0dadbf38
21293 changed files with 701351 additions and 428307 deletions

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.alerta;
@ -53,7 +58,10 @@ in
corsOrigins = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "List of URLs that can access the API for Cross-Origin Resource Sharing (CORS)";
default = [ "http://localhost" "http://localhost:5000" ];
default = [
"http://localhost"
"http://localhost:5000"
];
};
authenticationRequired = lib.mkOption {

View file

@ -1,10 +1,18 @@
{ lib, pkgs, config, ... }:
{
lib,
pkgs,
config,
...
}:
let
cfg = config.services.alloy;
in
{
meta = {
maintainers = with lib.maintainers; [ flokli hbjydev ];
maintainers = with lib.maintainers; [
flokli
hbjydev
];
};
options.services.alloy = {
@ -45,7 +53,10 @@ in
extraFlags = lib.mkOption {
type = with lib.types; listOf str;
default = [ ];
example = [ "--server.http.listen-addr=127.0.0.1:12346" "--disable-reporting" ];
example = [
"--server.http.listen-addr=127.0.0.1:12346"
"--disable-reporting"
];
description = ''
Extra command-line flags passed to {command}`alloy run`.
@ -54,7 +65,6 @@ in
};
};
config = lib.mkIf cfg.enable {
systemd.services.alloy = {
wantedBy = [ "multi-user.target" ];

View file

@ -1,7 +1,13 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.arbtt;
in {
in
{
options = {
services.arbtt = {
enable = lib.mkEnableOption "Arbtt statistics capture service";

View file

@ -1,28 +1,43 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.below;
cfgContents = lib.concatStringsSep "\n" (
lib.mapAttrsToList (n: v: ''${n} = "${v}"'') (lib.filterAttrs (_k: v: v != null) {
log_dir = cfg.dirs.log;
store_dir = cfg.dirs.store;
cgroup_filter_out = cfg.cgroupFilterOut;
})
lib.mapAttrsToList (n: v: ''${n} = "${v}"'') (
lib.filterAttrs (_k: v: v != null) {
log_dir = cfg.dirs.log;
store_dir = cfg.dirs.store;
cgroup_filter_out = cfg.cgroupFilterOut;
}
)
);
mkDisableOption = n: lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to enable ${n}.";
};
optionalType = ty: x: lib.mkOption (x // {
description = x.description;
type = (lib.types.nullOr ty);
default = null;
});
mkDisableOption =
n:
lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to enable ${n}.";
};
optionalType =
ty: x:
lib.mkOption (
x
// {
description = x.description;
type = (lib.types.nullOr ty);
default = null;
}
);
optionalPath = optionalType lib.types.path;
optionalStr = optionalType lib.types.str;
optionalInt = optionalType lib.types.int;
in {
in
{
options = {
services.below = {
enable = lib.mkEnableOption "'below' resource monitor";
@ -33,7 +48,7 @@ in {
};
collect = {
diskStats = mkDisableOption "dist_stat collection";
ioStats = lib.mkEnableOption "io.stat collection for cgroups";
ioStats = lib.mkEnableOption "io.stat collection for cgroups";
exitStats = mkDisableOption "eBPF-based exitstats";
};
compression.enable = lib.mkEnableOption "data compression";
@ -89,15 +104,19 @@ in {
serviceConfig.ExecStart = [
""
("${lib.getExe pkgs.below} record " + (lib.concatStringsSep " " (
lib.optional (!cfg.collect.diskStats) "--disable-disk-stat" ++
lib.optional cfg.collect.ioStats "--collect-io-stat" ++
lib.optional (!cfg.collect.exitStats) "--disable-exitstats" ++
lib.optional cfg.compression.enable "--compress" ++
(
"${lib.getExe pkgs.below} record "
+ (lib.concatStringsSep " " (
lib.optional (!cfg.collect.diskStats) "--disable-disk-stat"
++ lib.optional cfg.collect.ioStats "--collect-io-stat"
++ lib.optional (!cfg.collect.exitStats) "--disable-exitstats"
++ lib.optional cfg.compression.enable "--compress"
++
lib.optional (cfg.retention.size != null) "--store-size-limit ${toString cfg.retention.size}" ++
lib.optional (cfg.retention.time != null) "--retain-for-s ${toString cfg.retention.time}"
)))
lib.optional (cfg.retention.size != null) "--store-size-limit ${toString cfg.retention.size}"
++ lib.optional (cfg.retention.time != null) "--retain-for-s ${toString cfg.retention.time}"
))
)
];
};
};

View file

@ -1,10 +1,15 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.bosun;
configFile = pkgs.writeText "bosun.conf" ''
${lib.optionalString (cfg.opentsdbHost !=null) "tsdbHost = ${cfg.opentsdbHost}"}
${lib.optionalString (cfg.influxHost !=null) "influxHost = ${cfg.influxHost}"}
${lib.optionalString (cfg.opentsdbHost != null) "tsdbHost = ${cfg.opentsdbHost}"}
${lib.optionalString (cfg.influxHost != null) "influxHost = ${cfg.influxHost}"}
httpListen = ${cfg.listenAddress}
stateFile = ${cfg.stateFile}
ledisDir = ${cfg.ledisDir}
@ -13,7 +18,8 @@ let
${cfg.extraConfig}
'';
in {
in
{
options = {
@ -53,7 +59,7 @@ in {
default = null;
example = "localhost:8086";
description = ''
Host and port of the influxdb database.
Host and port of the influxdb database.
'';
};

View file

@ -1,8 +1,14 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.cadvisor;
in {
in
{
options = {
services.cadvisor = {
enable = lib.mkEnableOption "Cadvisor service";
@ -80,7 +86,7 @@ in {
extraOptions = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
default = [ ];
description = ''
Additional cadvisor options.
@ -91,18 +97,27 @@ in {
};
config = lib.mkMerge [
{ services.cadvisor.storageDriverPasswordFile = lib.mkIf (cfg.storageDriverPassword != "") (
lib.mkDefault (toString (pkgs.writeTextFile {
name = "cadvisor-storage-driver-password";
text = cfg.storageDriverPassword;
}))
{
services.cadvisor.storageDriverPasswordFile = lib.mkIf (cfg.storageDriverPassword != "") (
lib.mkDefault (
toString (
pkgs.writeTextFile {
name = "cadvisor-storage-driver-password";
text = cfg.storageDriverPassword;
}
)
)
);
}
(lib.mkIf cfg.enable {
systemd.services.cadvisor = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" "docker.service" "influxdb.service" ];
after = [
"network.target"
"docker.service"
"influxdb.service"
];
path = lib.optionals config.boot.zfs.enabled [ pkgs.zfs ];
@ -128,7 +143,7 @@ in {
''}
'';
serviceConfig.TimeoutStartSec=300;
serviceConfig.TimeoutStartSec = 300;
};
})
];

View file

@ -1,7 +1,9 @@
{ config
, lib
, pkgs
, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.certspotter;
@ -13,16 +15,21 @@ let
}
++ lib.optional (cfg.emailRecipients != [ ]) {
name = "email_recipients";
path = pkgs.writeText "certspotter-email_recipients" (builtins.concatStringsSep "\n" cfg.emailRecipients);
path = pkgs.writeText "certspotter-email_recipients" (
builtins.concatStringsSep "\n" cfg.emailRecipients
);
}
# always generate hooks dir when no emails are provided to allow running cert spotter with no hooks/emails
++ lib.optional (cfg.emailRecipients == [ ] || cfg.hooks != [ ]) {
name = "hooks.d";
path = pkgs.linkFarm "certspotter-hooks" (lib.imap1 (i: path: {
inherit path;
name = "hook${toString i}";
}) cfg.hooks);
});
path = pkgs.linkFarm "certspotter-hooks" (
lib.imap1 (i: path: {
inherit path;
name = "hook${toString i}";
}) cfg.hooks
);
}
);
in
{
options.services.certspotter = {
@ -52,7 +59,10 @@ in
type = with lib.types; listOf str;
description = "Domain names to watch. To monitor a domain with all subdomains, prefix its name with `.` (e.g. `.example.org`).";
default = [ ];
example = [ ".example.org" "another.example.com" ];
example = [
".example.org"
"another.example.com"
];
};
emailRecipients = lib.mkOption {
@ -65,7 +75,9 @@ in
type = with lib.types; listOf path;
description = ''
Scripts to run upon the detection of a new certificate. See `man 8 certspotter-script` or
[the GitHub page](https://github.com/SSLMate/certspotter/blob/${pkgs.certspotter.src.rev or "master"}/man/certspotter-script.md)
[the GitHub page](https://github.com/SSLMate/certspotter/blob/${
pkgs.certspotter.src.rev or "master"
}/man/certspotter-script.md)
for more info.
'';
default = [ ];
@ -97,13 +109,17 @@ in
}
];
services.certspotter.sendmailPath = let
inherit (config.security) wrapperDir;
inherit (config.services.mail) sendmailSetuidWrapper;
in lib.mkMerge [
(lib.mkIf (sendmailSetuidWrapper != null) (lib.mkOptionDefault "${wrapperDir}/${sendmailSetuidWrapper.program}"))
(lib.mkIf (sendmailSetuidWrapper == null) (lib.mkOptionDefault null))
];
services.certspotter.sendmailPath =
let
inherit (config.security) wrapperDir;
inherit (config.services.mail) sendmailSetuidWrapper;
in
lib.mkMerge [
(lib.mkIf (sendmailSetuidWrapper != null) (
lib.mkOptionDefault "${wrapperDir}/${sendmailSetuidWrapper.program}"
))
(lib.mkIf (sendmailSetuidWrapper == null) (lib.mkOptionDefault null))
];
users.users.certspotter = {
description = "Cert Spotter user";
@ -118,7 +134,8 @@ in
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
environment.CERTSPOTTER_CONFIG_DIR = configDir;
environment.SENDMAIL_PATH = if cfg.sendmailPath != null then cfg.sendmailPath else "/run/current-system/sw/bin/false";
environment.SENDMAIL_PATH =
if cfg.sendmailPath != null then cfg.sendmailPath else "/run/current-system/sw/bin/false";
script = ''
export CERTSPOTTER_STATE_DIR="$STATE_DIRECTORY"
cd "$CERTSPOTTER_STATE_DIR"

View file

@ -1,30 +1,36 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.collectd;
baseDirLine = ''BaseDir "${cfg.dataDir}"'';
unvalidated_conf = pkgs.writeText "collectd-unvalidated.conf" cfg.extraConfig;
conf = if cfg.validateConfig then
pkgs.runCommand "collectd.conf" {} ''
echo testing ${unvalidated_conf}
cp ${unvalidated_conf} collectd.conf
# collectd -t fails if BaseDir does not exist.
substituteInPlace collectd.conf --replace ${lib.escapeShellArgs [ baseDirLine ]} 'BaseDir "."'
${package}/bin/collectd -t -C collectd.conf
cp ${unvalidated_conf} $out
'' else unvalidated_conf;
conf =
if cfg.validateConfig then
pkgs.runCommand "collectd.conf" { } ''
echo testing ${unvalidated_conf}
cp ${unvalidated_conf} collectd.conf
# collectd -t fails if BaseDir does not exist.
substituteInPlace collectd.conf --replace ${lib.escapeShellArgs [ baseDirLine ]} 'BaseDir "."'
${package}/bin/collectd -t -C collectd.conf
cp ${unvalidated_conf} $out
''
else
unvalidated_conf;
package =
if cfg.buildMinimalPackage
then minimalPackage
else cfg.package;
package = if cfg.buildMinimalPackage then minimalPackage else cfg.package;
minimalPackage = cfg.package.override {
enabledPlugins = [ "syslog" ] ++ builtins.attrNames cfg.plugins;
};
in {
in
{
options.services.collectd = with lib.types; {
enable = lib.mkEnableOption "collectd agent";
@ -73,7 +79,7 @@ in {
};
include = lib.mkOption {
default = [];
default = [ ];
description = ''
Additional paths to load config from.
'';
@ -81,8 +87,12 @@ in {
};
plugins = lib.mkOption {
default = {};
example = { cpu = ""; memory = ""; network = "Server 192.168.1.1 25826"; };
default = { };
example = {
cpu = "";
memory = "";
network = "Server 192.168.1.1 25826";
};
description = ''
Attribute set of plugin names to plugin config segments
'';
@ -113,12 +123,14 @@ in {
NotifyLevel "OKAY"
</Plugin>
${lib.concatStrings (lib.mapAttrsToList (plugin: pluginConfig: ''
LoadPlugin ${plugin}
<Plugin "${plugin}">
${pluginConfig}
</Plugin>
'') cfg.plugins)}
${lib.concatStrings (
lib.mapAttrsToList (plugin: pluginConfig: ''
LoadPlugin ${plugin}
<Plugin "${plugin}">
${pluginConfig}
</Plugin>
'') cfg.plugins
)}
${lib.concatMapStrings (f: ''
Include "${f}"
@ -150,7 +162,7 @@ in {
};
users.groups = lib.optionalAttrs (cfg.user == "collectd") {
collectd = {};
collectd = { };
};
};
}

View file

@ -1,11 +1,17 @@
# A general watchdog for the linux operating system that should run in the
# background at all times to ensure a realtime process won't hang the machine
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (pkgs) das_watchdog;
in {
in
{
###### interface
options = {
@ -18,7 +24,10 @@ in {
environment.systemPackages = [ das_watchdog ];
systemd.services.das_watchdog = {
description = "Watchdog to ensure a realtime process won't hang the machine";
after = [ "multi-user.target" "sound.target" ];
after = [
"multi-user.target"
"sound.target"
];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = "root";

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.do-agent;
@ -14,7 +19,10 @@ in
systemd.services.do-agent = {
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = [ "" "${pkgs.do-agent}/bin/do-agent --syslog" ];
ExecStart = [
""
"${pkgs.do-agent}/bin/do-agent --syslog"
];
DynamicUser = true;
};
};

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.goss;
@ -6,7 +11,8 @@ let
settingsFormat = pkgs.formats.yaml { };
configFile = settingsFormat.generate "goss.yaml" cfg.settings;
in {
in
{
meta = {
doc = ./goss.md;
maintainers = [ lib.maintainers.anthonyroussel ];

View file

@ -1,4 +1,10 @@
{ lib, pkgs, config, generators, ... }:
{
lib,
pkgs,
config,
generators,
...
}:
let
cfg = config.services.grafana-agent;
settingsFormat = pkgs.formats.yaml { };
@ -6,7 +12,10 @@ let
in
{
meta = {
maintainers = with lib.maintainers; [ flokli zimbatm ];
maintainers = with lib.maintainers; [
flokli
zimbatm
];
};
options.services.grafana-agent = {
@ -34,7 +43,10 @@ in
extraFlags = lib.mkOption {
type = with lib.types; listOf str;
default = [ ];
example = [ "-enable-features=integrations-next" "-disable-reporting" ];
example = [
"-enable-features=integrations-next"
"-disable-reporting"
];
description = ''
Extra command-line flags passed to {command}`grafana-agent`.
@ -68,43 +80,49 @@ in
}
'';
example = {
metrics.global.remote_write = [{
url = "\${METRICS_REMOTE_WRITE_URL}";
basic_auth.username = "\${METRICS_REMOTE_WRITE_USERNAME}";
basic_auth.password_file = "\${CREDENTIALS_DIRECTORY}/metrics_remote_write_password";
}];
logs.configs = [{
name = "default";
scrape_configs = [
{
job_name = "journal";
journal = {
max_age = "12h";
labels.job = "systemd-journal";
};
relabel_configs = [
{
source_labels = [ "__journal__systemd_unit" ];
target_label = "systemd_unit";
}
{
source_labels = [ "__journal__hostname" ];
target_label = "nodename";
}
{
source_labels = [ "__journal_syslog_identifier" ];
target_label = "syslog_identifier";
}
];
}
];
positions.filename = "\${STATE_DIRECTORY}/loki_positions.yaml";
clients = [{
url = "\${LOGS_REMOTE_WRITE_URL}";
basic_auth.username = "\${LOGS_REMOTE_WRITE_USERNAME}";
basic_auth.password_file = "\${CREDENTIALS_DIRECTORY}/logs_remote_write_password";
}];
}];
metrics.global.remote_write = [
{
url = "\${METRICS_REMOTE_WRITE_URL}";
basic_auth.username = "\${METRICS_REMOTE_WRITE_USERNAME}";
basic_auth.password_file = "\${CREDENTIALS_DIRECTORY}/metrics_remote_write_password";
}
];
logs.configs = [
{
name = "default";
scrape_configs = [
{
job_name = "journal";
journal = {
max_age = "12h";
labels.job = "systemd-journal";
};
relabel_configs = [
{
source_labels = [ "__journal__systemd_unit" ];
target_label = "systemd_unit";
}
{
source_labels = [ "__journal__hostname" ];
target_label = "nodename";
}
{
source_labels = [ "__journal_syslog_identifier" ];
target_label = "syslog_identifier";
}
];
}
];
positions.filename = "\${STATE_DIRECTORY}/loki_positions.yaml";
clients = [
{
url = "\${LOGS_REMOTE_WRITE_URL}";
basic_auth.username = "\${LOGS_REMOTE_WRITE_USERNAME}";
basic_auth.password_file = "\${CREDENTIALS_DIRECTORY}/logs_remote_write_password";
}
];
}
];
};
};
};

View file

@ -1,11 +1,17 @@
{ lib, pkgs, config, ... }:
{
lib,
pkgs,
config,
...
}:
let
cfg = config.services.grafana-image-renderer;
format = pkgs.formats.json { };
configFile = format.generate "grafana-image-renderer-config.json" cfg.settings;
in {
in
{
options.services.grafana-image-renderer = {
enable = lib.mkEnableOption "grafana-image-renderer";
@ -34,7 +40,12 @@ in {
'';
};
logging.level = lib.mkOption {
type = lib.types.enum [ "error" "warning" "info" "debug" ];
type = lib.types.enum [
"error"
"warning"
"info"
"debug"
];
default = "info";
description = ''
The log-level of the {file}`grafana-image-renderer.service`-unit.
@ -58,7 +69,11 @@ in {
};
mode = lib.mkOption {
default = "default";
type = lib.types.enum [ "default" "reusable" "clustered" ];
type = lib.types.enum [
"default"
"reusable"
"clustered"
];
description = ''
Rendering mode of `grafana-image-renderer`:
@ -82,7 +97,7 @@ in {
};
};
default = {};
default = { };
description = ''
Configuration attributes for `grafana-image-renderer`.
@ -95,7 +110,8 @@ in {
config = lib.mkIf cfg.enable {
assertions = [
{ assertion = cfg.provisionGrafana -> config.services.grafana.enable;
{
assertion = cfg.provisionGrafana -> config.services.grafana.enable;
message = ''
To provision a Grafana instance to use grafana-image-renderer,
`services.grafana.enable` must be set to `true`!

View file

@ -1,8 +1,14 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.grafana_reporter;
in {
in
{
options.services.grafana_reporter = {
enable = lib.mkEnableOption "grafana_reporter";
@ -10,7 +16,10 @@ in {
protocol = lib.mkOption {
description = "Grafana protocol.";
default = "http";
type = lib.types.enum ["http" "https"];
type = lib.types.enum [
"http"
"https"
];
};
addr = lib.mkOption {
description = "Grafana address.";
@ -47,18 +56,20 @@ in {
config = lib.mkIf cfg.enable {
systemd.services.grafana_reporter = {
description = "Grafana Reporter Service Daemon";
wantedBy = ["multi-user.target"];
after = ["network.target"];
serviceConfig = let
args = lib.concatStringsSep " " [
"-proto ${cfg.grafana.protocol}://"
"-ip ${cfg.grafana.addr}:${toString cfg.grafana.port}"
"-port :${toString cfg.port}"
"-templates ${cfg.templateDir}"
];
in {
ExecStart = "${pkgs.grafana-reporter}/bin/grafana-reporter ${args}";
};
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig =
let
args = lib.concatStringsSep " " [
"-proto ${cfg.grafana.protocol}://"
"-ip ${cfg.grafana.addr}:${toString cfg.grafana.port}"
"-port :${toString cfg.port}"
"-templates ${cfg.templateDir}"
];
in
{
ExecStart = "${pkgs.grafana-reporter}/bin/grafana-reporter ${args}";
};
};
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, options, pkgs, ... }:
{
config,
lib,
options,
pkgs,
...
}:
let
cfg = config.services.graphite;
opt = options.services.graphite;
@ -7,17 +13,20 @@ let
dataDir = cfg.dataDir;
staticDir = cfg.dataDir + "/static";
graphiteLocalSettingsDir = pkgs.runCommand "graphite_local_settings" {
inherit graphiteLocalSettings;
preferLocalBuild = true;
} ''
mkdir -p $out
ln -s $graphiteLocalSettings $out/graphite_local_settings.py
'';
graphiteLocalSettingsDir =
pkgs.runCommand "graphite_local_settings"
{
inherit graphiteLocalSettings;
preferLocalBuild = true;
}
''
mkdir -p $out
ln -s $graphiteLocalSettings $out/graphite_local_settings.py
'';
graphiteLocalSettings = pkgs.writeText "graphite_local_settings.py" (
"STATIC_ROOT = '${staticDir}'\n" +
lib.optionalString (config.time.timeZone != null) "TIME_ZONE = '${config.time.timeZone}'\n"
"STATIC_ROOT = '${staticDir}'\n"
+ lib.optionalString (config.time.timeZone != null) "TIME_ZONE = '${config.time.timeZone}'\n"
+ cfg.web.extraConfig
);
@ -41,27 +50,31 @@ let
];
};
carbonOpts = name: with config.ids; ''
--nodaemon --syslog --prefix=${name} --pidfile /run/${name}/${name}.pid ${name}
'';
carbonOpts =
name: with config.ids; ''
--nodaemon --syslog --prefix=${name} --pidfile /run/${name}/${name}.pid ${name}
'';
carbonEnv = {
PYTHONPATH = let
cenv = pkgs.python3.buildEnv.override {
extraLibs = [ pkgs.python3Packages.carbon ];
};
in "${cenv}/${pkgs.python3.sitePackages}";
PYTHONPATH =
let
cenv = pkgs.python3.buildEnv.override {
extraLibs = [ pkgs.python3Packages.carbon ];
};
in
"${cenv}/${pkgs.python3.sitePackages}";
GRAPHITE_ROOT = dataDir;
GRAPHITE_CONF_DIR = configDir;
GRAPHITE_STORAGE_DIR = dataDir;
};
in {
in
{
imports = [
(lib.mkRemovedOptionModule ["services" "graphite" "api"] "")
(lib.mkRemovedOptionModule ["services" "graphite" "beacon"] "")
(lib.mkRemovedOptionModule ["services" "graphite" "pager"] "")
(lib.mkRemovedOptionModule [ "services" "graphite" "api" ] "")
(lib.mkRemovedOptionModule [ "services" "graphite" "beacon" ] "")
(lib.mkRemovedOptionModule [ "services" "graphite" "pager" ] "")
];
###### interface
@ -247,7 +260,7 @@ in {
};
extraConfig = lib.mkOption {
default = {};
default = { };
description = ''
Extra seyren configuration. See
<https://github.com/scobal/seyren#config>
@ -267,60 +280,72 @@ in {
config = lib.mkMerge [
(lib.mkIf cfg.carbon.enableCache {
systemd.services.carbonCache = let name = "carbon-cache"; in {
description = "Graphite Data Storage Backend";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
environment = carbonEnv;
serviceConfig = {
Slice = "system-graphite.slice";
RuntimeDirectory = name;
ExecStart = "${pkgs.python3Packages.twisted}/bin/twistd ${carbonOpts name}";
User = "graphite";
Group = "graphite";
PermissionsStartOnly = true;
PIDFile="/run/${name}/${name}.pid";
systemd.services.carbonCache =
let
name = "carbon-cache";
in
{
description = "Graphite Data Storage Backend";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
environment = carbonEnv;
serviceConfig = {
Slice = "system-graphite.slice";
RuntimeDirectory = name;
ExecStart = "${pkgs.python3Packages.twisted}/bin/twistd ${carbonOpts name}";
User = "graphite";
Group = "graphite";
PermissionsStartOnly = true;
PIDFile = "/run/${name}/${name}.pid";
};
preStart = ''
install -dm0700 -o graphite -g graphite ${cfg.dataDir}
install -dm0700 -o graphite -g graphite ${cfg.dataDir}/whisper
'';
};
preStart = ''
install -dm0700 -o graphite -g graphite ${cfg.dataDir}
install -dm0700 -o graphite -g graphite ${cfg.dataDir}/whisper
'';
};
})
(lib.mkIf cfg.carbon.enableAggregator {
systemd.services.carbonAggregator = let name = "carbon-aggregator"; in {
enable = cfg.carbon.enableAggregator;
description = "Carbon Data Aggregator";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
environment = carbonEnv;
serviceConfig = {
Slice = "system-graphite.slice";
RuntimeDirectory = name;
ExecStart = "${pkgs.python3Packages.twisted}/bin/twistd ${carbonOpts name}";
User = "graphite";
Group = "graphite";
PIDFile="/run/${name}/${name}.pid";
systemd.services.carbonAggregator =
let
name = "carbon-aggregator";
in
{
enable = cfg.carbon.enableAggregator;
description = "Carbon Data Aggregator";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
environment = carbonEnv;
serviceConfig = {
Slice = "system-graphite.slice";
RuntimeDirectory = name;
ExecStart = "${pkgs.python3Packages.twisted}/bin/twistd ${carbonOpts name}";
User = "graphite";
Group = "graphite";
PIDFile = "/run/${name}/${name}.pid";
};
};
};
})
(lib.mkIf cfg.carbon.enableRelay {
systemd.services.carbonRelay = let name = "carbon-relay"; in {
description = "Carbon Data Relay";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
environment = carbonEnv;
serviceConfig = {
Slice = "system-graphite.slice";
RuntimeDirectory = name;
ExecStart = "${pkgs.python3Packages.twisted}/bin/twistd ${carbonOpts name}";
User = "graphite";
Group = "graphite";
PIDFile="/run/${name}/${name}.pid";
systemd.services.carbonRelay =
let
name = "carbon-relay";
in
{
description = "Carbon Data Relay";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
environment = carbonEnv;
serviceConfig = {
Slice = "system-graphite.slice";
RuntimeDirectory = name;
ExecStart = "${pkgs.python3Packages.twisted}/bin/twistd ${carbonOpts name}";
User = "graphite";
Group = "graphite";
PIDFile = "/run/${name}/${name}.pid";
};
};
};
})
(lib.mkIf (cfg.carbon.enableCache || cfg.carbon.enableAggregator || cfg.carbon.enableRelay) {
@ -336,19 +361,21 @@ in {
after = [ "network.target" ];
path = [ pkgs.perl ];
environment = {
PYTHONPATH = let
PYTHONPATH =
let
penv = pkgs.python3.buildEnv.override {
extraLibs = [
pkgs.python3Packages.graphite-web
];
};
penvPack = "${penv}/${pkgs.python3.sitePackages}";
in lib.concatStringsSep ":" [
"${graphiteLocalSettingsDir}"
"${penvPack}"
# explicitly adding pycairo in path because it cannot be imported via buildEnv
"${pkgs.python3Packages.pycairo}/${pkgs.python3.sitePackages}"
];
in
lib.concatStringsSep ":" [
"${graphiteLocalSettingsDir}"
"${penvPack}"
# explicitly adding pycairo in path because it cannot be imported via buildEnv
"${pkgs.python3Packages.pycairo}/${pkgs.python3.sitePackages}"
];
DJANGO_SETTINGS_MODULE = "graphite.settings";
GRAPHITE_SETTINGS_MODULE = "graphite_local_settings";
GRAPHITE_CONF_DIR = configDir;
@ -394,7 +421,10 @@ in {
systemd.services.seyren = {
description = "Graphite Alerting Dashboard";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" "mongodb.service" ];
after = [
"network.target"
"mongodb.service"
];
environment = seyrenConfig;
serviceConfig = {
ExecStart = "${pkgs.seyren}/bin/seyren -httpPort ${toString cfg.seyren.port}";
@ -414,22 +444,28 @@ in {
services.mongodb.enable = lib.mkDefault true;
})
(lib.mkIf (
cfg.carbon.enableCache || cfg.carbon.enableAggregator || cfg.carbon.enableRelay ||
cfg.web.enable || cfg.seyren.enable
) {
systemd.slices.system-graphite = {
description = "Graphite Graphing System Slice";
documentation = [ "https://graphite.readthedocs.io/en/latest/overview.html" ];
};
(lib.mkIf
(
cfg.carbon.enableCache
|| cfg.carbon.enableAggregator
|| cfg.carbon.enableRelay
|| cfg.web.enable
|| cfg.seyren.enable
)
{
systemd.slices.system-graphite = {
description = "Graphite Graphing System Slice";
documentation = [ "https://graphite.readthedocs.io/en/latest/overview.html" ];
};
users.users.graphite = {
uid = config.ids.uids.graphite;
group = "graphite";
description = "Graphite daemon user";
home = dataDir;
};
users.groups.graphite.gid = config.ids.gids.graphite;
})
users.users.graphite = {
uid = config.ids.uids.graphite;
group = "graphite";
description = "Graphite daemon user";
home = dataDir;
};
users.groups.graphite.gid = config.ids.gids.graphite;
}
)
];
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.hdapsd;
hdapsd = [ pkgs.hdapsd ];
@ -6,9 +11,9 @@ in
{
options = {
services.hdapsd.enable = lib.mkEnableOption ''
Hard Drive Active Protection System Daemon,
devices are detected and managed automatically by udev and systemd
'';
Hard Drive Active Protection System Daemon,
devices are detected and managed automatically by udev and systemd
'';
};
config = lib.mkIf cfg.enable {

View file

@ -1,7 +1,13 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.heapster;
in {
in
{
options.services.heapster = {
enable = lib.mkEnableOption "Heapster monitoring";
@ -28,8 +34,11 @@ in {
config = lib.mkIf cfg.enable {
systemd.services.heapster = {
wantedBy = ["multi-user.target"];
after = ["cadvisor.service" "kube-apiserver.service"];
wantedBy = [ "multi-user.target" ];
after = [
"cadvisor.service"
"kube-apiserver.service"
];
serviceConfig = {
ExecStart = "${cfg.package}/bin/heapster --source=${cfg.source} --sink=${cfg.sink} ${cfg.extraOpts}";
@ -42,6 +51,6 @@ in {
group = "heapster";
description = "Heapster user";
};
users.groups.heapster = {};
users.groups.heapster = { };
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.incron;
@ -51,7 +56,7 @@ in
extraPackages = lib.mkOption {
type = lib.types.listOf lib.types.package;
default = [];
default = [ ];
example = lib.literalExpression "[ pkgs.rsync ]";
description = "Extra packages available to the system incrontab.";
};
@ -62,13 +67,14 @@ in
config = lib.mkIf cfg.enable {
warnings = lib.optional (cfg.allow != null && cfg.deny != null)
"If `services.incron.allow` is set then `services.incron.deny` will be ignored.";
warnings = lib.optional (
cfg.allow != null && cfg.deny != null
) "If `services.incron.allow` is set then `services.incron.deny` will be ignored.";
environment.systemPackages = [ pkgs.incron ];
security.wrappers.incrontab =
{ setuid = true;
security.wrappers.incrontab = {
setuid = true;
owner = "root";
group = "root";
source = "${pkgs.incron}/bin/incrontab";

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.kapacitor;

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.karma;
yaml = pkgs.formats.yaml { };
@ -21,13 +26,13 @@ in
environment = lib.mkOption {
type = with lib.types; attrsOf str;
default = {};
default = { };
description = ''
Additional environment variables to provide to karma.
'';
example = {
ALERTMANAGER_URI = "https://alertmanager.example.com";
ALERTMANAGER_NAME= "single";
ALERTMANAGER_NAME = "single";
};
};
@ -41,7 +46,7 @@ in
extraOptions = lib.mkOption {
type = with lib.types; listOf str;
default = [];
default = [ ];
description = ''
Extra command line options.
'';

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.kthxbye;
in
@ -19,7 +24,7 @@ in
extraOptions = lib.mkOption {
type = with lib.types; listOf str;
default = [];
default = [ ];
description = ''
Extra command line options.

View file

@ -1,16 +1,29 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) escapeShellArgs mkEnableOption mkIf mkOption types;
inherit (lib)
escapeShellArgs
mkEnableOption
mkIf
mkOption
types
;
cfg = config.services.loki;
prettyJSON = conf:
prettyJSON =
conf:
pkgs.runCommand "loki-config.json" { } ''
echo '${builtins.toJSON conf}' | ${pkgs.jq}/bin/jq 'del(._module)' > $out
'';
in {
in
{
options.services.loki = {
enable = mkEnableOption "loki";
@ -41,8 +54,8 @@ in {
};
configuration = mkOption {
type = (pkgs.formats.json {}).type;
default = {};
type = (pkgs.formats.json { }).type;
default = { };
description = ''
Specify the configuration for Loki in Nix.
'';
@ -58,7 +71,7 @@ in {
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
default = [ ];
example = [ "--server.http-listen-port=3101" ];
description = ''
Specify a list of additional command line flags,
@ -68,17 +81,19 @@ in {
};
config = mkIf cfg.enable {
assertions = [{
assertion = (
(cfg.configuration == {} -> cfg.configFile != null) &&
(cfg.configFile != null -> cfg.configuration == {})
);
message = ''
Please specify either
'services.loki.configuration' or
'services.loki.configFile'.
'';
}];
assertions = [
{
assertion = (
(cfg.configuration == { } -> cfg.configFile != null)
&& (cfg.configFile != null -> cfg.configuration == { })
);
message = ''
Please specify either
'services.loki.configuration' or
'services.loki.configFile'.
'';
}
];
environment.systemPackages = [ cfg.package ]; # logcli
@ -97,34 +112,40 @@ in {
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = let
conf = if cfg.configFile == null
then
# Config validation may fail when using extraFlags = [ "-config.expand-env=true" ].
# To work around this, we simply skip it when extraFlags is not empty.
if cfg.extraFlags == []
then validateConfig (prettyJSON cfg.configuration)
else prettyJSON cfg.configuration
else cfg.configFile;
validateConfig = file:
pkgs.runCommand "validate-loki-conf" {
nativeBuildInputs = [ cfg.package ];
} ''
loki -verify-config -config.file "${file}"
ln -s "${file}" "$out"
'';
in
{
ExecStart = "${cfg.package}/bin/loki --config.file=${conf} ${escapeShellArgs cfg.extraFlags}";
User = cfg.user;
Restart = "always";
PrivateTmp = true;
ProtectHome = true;
ProtectSystem = "full";
DevicePolicy = "closed";
NoNewPrivileges = true;
WorkingDirectory = cfg.dataDir;
};
serviceConfig =
let
conf =
if cfg.configFile == null then
# Config validation may fail when using extraFlags = [ "-config.expand-env=true" ].
# To work around this, we simply skip it when extraFlags is not empty.
if cfg.extraFlags == [ ] then
validateConfig (prettyJSON cfg.configuration)
else
prettyJSON cfg.configuration
else
cfg.configFile;
validateConfig =
file:
pkgs.runCommand "validate-loki-conf"
{
nativeBuildInputs = [ cfg.package ];
}
''
loki -verify-config -config.file "${file}"
ln -s "${file}" "$out"
'';
in
{
ExecStart = "${cfg.package}/bin/loki --config.file=${conf} ${escapeShellArgs cfg.extraFlags}";
User = cfg.user;
Restart = "always";
PrivateTmp = true;
ProtectHome = true;
ProtectSystem = "full";
DevicePolicy = "closed";
NoNewPrivileges = true;
WorkingDirectory = cfg.dataDir;
};
};
};
}

View file

@ -1,11 +1,17 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.longview;
runDir = "/run/longview";
configsDir = "${runDir}/longview.d";
in {
in
{
options = {
services.longview = {
@ -101,57 +107,78 @@ in {
};
config = lib.mkIf cfg.enable {
systemd.services.longview =
{ description = "Longview Metrics Collection";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "forking";
serviceConfig.ExecStop = "-${pkgs.coreutils}/bin/kill -TERM $MAINPID";
serviceConfig.ExecReload = "-${pkgs.coreutils}/bin/kill -HUP $MAINPID";
serviceConfig.PIDFile = "${runDir}/longview.pid";
serviceConfig.ExecStart = "${pkgs.longview}/bin/longview";
preStart = ''
systemd.services.longview = {
description = "Longview Metrics Collection";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "forking";
serviceConfig.ExecStop = "-${pkgs.coreutils}/bin/kill -TERM $MAINPID";
serviceConfig.ExecReload = "-${pkgs.coreutils}/bin/kill -HUP $MAINPID";
serviceConfig.PIDFile = "${runDir}/longview.pid";
serviceConfig.ExecStart = "${pkgs.longview}/bin/longview";
preStart =
''
umask 077
mkdir -p ${configsDir}
'' + (lib.optionalString (cfg.apiKeyFile != null) ''
''
+ (lib.optionalString (cfg.apiKeyFile != null) ''
cp --no-preserve=all "${cfg.apiKeyFile}" ${runDir}/longview.key
'') + (lib.optionalString (cfg.apacheStatusUrl != "") ''
'')
+ (lib.optionalString (cfg.apacheStatusUrl != "") ''
cat > ${configsDir}/Apache.conf <<EOF
location ${cfg.apacheStatusUrl}?auto
EOF
'') + (lib.optionalString (cfg.mysqlUser != "" && cfg.mysqlPasswordFile != null) ''
'')
+ (lib.optionalString (cfg.mysqlUser != "" && cfg.mysqlPasswordFile != null) ''
cat > ${configsDir}/MySQL.conf <<EOF
username ${cfg.mysqlUser}
password `head -n1 "${cfg.mysqlPasswordFile}"`
EOF
'') + (lib.optionalString (cfg.nginxStatusUrl != "") ''
'')
+ (lib.optionalString (cfg.nginxStatusUrl != "") ''
cat > ${configsDir}/Nginx.conf <<EOF
location ${cfg.nginxStatusUrl}
EOF
'');
};
};
warnings = let warn = k: lib.optional (cfg.${k} != "")
"config.services.longview.${k} is insecure. Use ${k}File instead.";
in lib.concatMap warn [ "apiKey" "mysqlPassword" ];
warnings =
let
warn =
k: lib.optional (cfg.${k} != "") "config.services.longview.${k} is insecure. Use ${k}File instead.";
in
lib.concatMap warn [
"apiKey"
"mysqlPassword"
];
assertions = [
{ assertion = cfg.apiKeyFile != null;
{
assertion = cfg.apiKeyFile != null;
message = "Longview needs an API key configured";
}
];
# Create API key file if not configured.
services.longview.apiKeyFile = lib.mkIf (cfg.apiKey != "")
(lib.mkDefault (toString (pkgs.writeTextFile {
name = "longview.key";
text = cfg.apiKey;
})));
services.longview.apiKeyFile = lib.mkIf (cfg.apiKey != "") (
lib.mkDefault (
toString (
pkgs.writeTextFile {
name = "longview.key";
text = cfg.apiKey;
}
)
)
);
# Create MySQL password file if not configured.
services.longview.mysqlPasswordFile = lib.mkDefault (toString (pkgs.writeTextFile {
name = "mysql-password-file";
text = cfg.mysqlPassword;
}));
services.longview.mysqlPasswordFile = lib.mkDefault (
toString (
pkgs.writeTextFile {
name = "mysql-password-file";
text = cfg.mysqlPassword;
}
)
);
};
}

View file

@ -1,8 +1,14 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.mackerel-agent;
settingsFmt = pkgs.formats.toml {};
in {
settingsFmt = pkgs.formats.toml { };
in
{
options.services.mackerel-agent = {
enable = lib.mkEnableOption "mackerel.io agent";
@ -33,7 +39,7 @@ in {
<https://mackerel.io/docs/entry/spec/agent>
'';
default = {};
default = { };
example = {
verbose = false;
silent = false;
@ -44,19 +50,28 @@ in {
options.host_status = {
on_start = lib.mkOption {
type = lib.types.enum [ "working" "standby" "maintenance" "poweroff" ];
type = lib.types.enum [
"working"
"standby"
"maintenance"
"poweroff"
];
description = "Host status after agent startup.";
default = "working";
};
on_stop = lib.mkOption {
type = lib.types.enum [ "working" "standby" "maintenance" "poweroff" ];
type = lib.types.enum [
"working"
"standby"
"maintenance"
"poweroff"
];
description = "Host status after agent shutdown.";
default = "poweroff";
};
};
options.diagnostic =
lib.mkEnableOption "collecting memory usage for the agent itself";
options.diagnostic = lib.mkEnableOption "collecting memory usage for the agent itself";
};
};
};
@ -82,7 +97,10 @@ in {
systemd.services.mackerel-agent = {
description = "mackerel.io agent";
wants = [ "network-online.target" ];
after = [ "network-online.target" "nss-lookup.target" ];
after = [
"network-online.target"
"nss-lookup.target"
];
wantedBy = [ "multi-user.target" ];
environment = {
MACKEREL_PLUGIN_WORKDIR = lib.mkDefault "%C/mackerel-agent";

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
@ -12,7 +17,7 @@ let
;
cfg = config.services.metricbeat;
settingsFormat = pkgs.formats.yaml {};
settingsFormat = pkgs.formats.yaml { };
in
{
@ -39,30 +44,47 @@ in
See <https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html>.
'';
default = {};
type = types.attrsOf (types.submodule ({ name, ... }: {
freeformType = settingsFormat.type;
options = {
module = mkOption {
type = types.str;
default = name;
description = ''
The name of the module.
default = { };
type = types.attrsOf (
types.submodule (
{ name, ... }:
{
freeformType = settingsFormat.type;
options = {
module = mkOption {
type = types.str;
default = name;
description = ''
The name of the module.
Look for the value after `module:` on the individual
module pages linked from <https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html>.
'';
};
};
}));
Look for the value after `module:` on the individual
module pages linked from <https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html>.
'';
};
};
}
)
);
example = {
system = {
metricsets = ["cpu" "load" "memory" "network" "process" "process_summary" "uptime" "socket_summary"];
metricsets = [
"cpu"
"load"
"memory"
"network"
"process"
"process_summary"
"uptime"
"socket_summary"
];
enabled = true;
period = "10s";
processes = [".*"];
cpu.metrics = ["percentages" "normalized_percentages"];
core.metrics = ["percentages"];
processes = [ ".*" ];
cpu.metrics = [
"percentages"
"normalized_percentages"
];
core.metrics = [ "percentages" ];
};
};
};
@ -83,7 +105,7 @@ in
tags = mkOption {
type = types.listOf types.str;
default = [];
default = [ ];
description = ''
Tags to place on the shipped metrics.
See <https://www.elastic.co/guide/en/beats/metricbeat/current/configuration-general-options.html#_tags_2>.
@ -92,7 +114,7 @@ in
metricbeat.modules = mkOption {
type = types.listOf settingsFormat.type;
default = [];
default = [ ];
internal = true;
description = ''
The metric collecting modules. Use [](#opt-services.metricbeat.modules) instead.
@ -102,7 +124,7 @@ in
};
};
};
default = {};
default = { };
description = ''
Configuration for metricbeat. See <https://www.elastic.co/guide/en/beats/metricbeat/current/configuring-howto-metricbeat.html> for supported values.
'';
@ -116,7 +138,7 @@ in
assertions = [
{
# empty modules would cause a failure at runtime
assertion = cfg.settings.metricbeat.modules != [];
assertion = cfg.settings.metricbeat.modules != [ ];
message = "services.metricbeat: You must configure one or more modules.";
}
];

View file

@ -1,18 +1,31 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) escapeShellArgs mkEnableOption mkPackageOption mkIf mkOption types;
inherit (lib)
escapeShellArgs
mkEnableOption
mkPackageOption
mkIf
mkOption
types
;
cfg = config.services.mimir;
settingsFormat = pkgs.formats.yaml {};
in {
settingsFormat = pkgs.formats.yaml { };
in
{
options.services.mimir = {
enable = mkEnableOption "mimir";
configuration = mkOption {
type = (pkgs.formats.json {}).type;
default = {};
type = (pkgs.formats.json { }).type;
default = { };
description = ''
Specify the configuration for Mimir in Nix.
'';
@ -30,7 +43,7 @@ in {
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
default = [ ];
example = [ "--config.expand-env=true" ];
description = ''
Specify a list of additional command line flags,
@ -43,37 +56,42 @@ in {
# for mimirtool
environment.systemPackages = [ cfg.package ];
assertions = [{
assertion = (
(cfg.configuration == {} -> cfg.configFile != null) &&
(cfg.configFile != null -> cfg.configuration == {})
);
message = ''
Please specify either
'services.mimir.configuration' or
'services.mimir.configFile'.
'';
}];
assertions = [
{
assertion = (
(cfg.configuration == { } -> cfg.configFile != null)
&& (cfg.configFile != null -> cfg.configuration == { })
);
message = ''
Please specify either
'services.mimir.configuration' or
'services.mimir.configFile'.
'';
}
];
systemd.services.mimir = {
description = "mimir Service Daemon";
wantedBy = [ "multi-user.target" ];
serviceConfig = let
conf = if cfg.configFile == null
then settingsFormat.generate "config.yaml" cfg.configuration
else cfg.configFile;
in
{
ExecStart = "${cfg.package}/bin/mimir --config.file=${conf} ${escapeShellArgs cfg.extraFlags}";
DynamicUser = true;
Restart = "always";
ProtectSystem = "full";
DevicePolicy = "closed";
NoNewPrivileges = true;
WorkingDirectory = "/var/lib/mimir";
StateDirectory = "mimir";
};
serviceConfig =
let
conf =
if cfg.configFile == null then
settingsFormat.generate "config.yaml" cfg.configuration
else
cfg.configFile;
in
{
ExecStart = "${cfg.package}/bin/mimir --config.file=${conf} ${escapeShellArgs cfg.extraFlags}";
DynamicUser = true;
Restart = "always";
ProtectSystem = "full";
DevicePolicy = "closed";
NoNewPrivileges = true;
WorkingDirectory = "/var/lib/mimir";
StateDirectory = "mimir";
};
};
};
}

View file

@ -1,4 +1,9 @@
{config, pkgs, lib, ...}:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.monit;
in

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
# TODO: support munin-async
# TODO: LWP/Pg perl libs aren't recognized
# TODO: support fastcgi
@ -11,60 +16,57 @@ let
nodeCfg = config.services.munin-node;
cronCfg = config.services.munin-cron;
muninConf = pkgs.writeText "munin.conf"
''
dbdir /var/lib/munin
htmldir /var/www/munin
logdir /var/log/munin
rundir /run/munin
muninConf = pkgs.writeText "munin.conf" ''
dbdir /var/lib/munin
htmldir /var/www/munin
logdir /var/log/munin
rundir /run/munin
${lib.optionalString (cronCfg.extraCSS != "") "staticdir ${customStaticDir}"}
${lib.optionalString (cronCfg.extraCSS != "") "staticdir ${customStaticDir}"}
${cronCfg.extraGlobalConfig}
${cronCfg.extraGlobalConfig}
${cronCfg.hosts}
'';
${cronCfg.hosts}
'';
nodeConf = pkgs.writeText "munin-node.conf"
''
log_level 3
log_file Sys::Syslog
port 4949
host *
background 0
user root
group root
host_name ${config.networking.hostName}
setsid 0
nodeConf = pkgs.writeText "munin-node.conf" ''
log_level 3
log_file Sys::Syslog
port 4949
host *
background 0
user root
group root
host_name ${config.networking.hostName}
setsid 0
# wrapped plugins by makeWrapper being with dots
ignore_file ^\.
# wrapped plugins by makeWrapper being with dots
ignore_file ^\.
allow ^::1$
allow ^127\.0\.0\.1$
allow ^::1$
allow ^127\.0\.0\.1$
${nodeCfg.extraConfig}
'';
${nodeCfg.extraConfig}
'';
pluginConf = pkgs.writeText "munin-plugin-conf"
''
[hddtemp_smartctl]
user root
group root
pluginConf = pkgs.writeText "munin-plugin-conf" ''
[hddtemp_smartctl]
user root
group root
[meminfo]
user root
group root
[meminfo]
user root
group root
[ipmi*]
user root
group root
[ipmi*]
user root
group root
[munin*]
env.UPDATE_STATSFILE /var/lib/munin/munin-update.stats
[munin*]
env.UPDATE_STATSFILE /var/lib/munin/munin-update.stats
${nodeCfg.extraPluginConfig}
'';
${nodeCfg.extraPluginConfig}
'';
pluginConfDir = pkgs.stdenv.mkDerivation {
name = "munin-plugin-conf.d";
@ -77,16 +79,14 @@ let
# Copy one Munin plugin into the Nix store with a specific name.
# This is suitable for use with plugins going directly into /etc/munin/plugins,
# i.e. munin.extraPlugins.
internOnePlugin = { name, path }:
"cp -a '${path}' '${name}'";
internOnePlugin = { name, path }: "cp -a '${path}' '${name}'";
# Copy an entire tree of Munin plugins into a single directory in the Nix
# store, with no renaming. The output is suitable for use with
# munin-node-configure --suggest, i.e. munin.extraAutoPlugins.
# Note that this flattens the input; this is intentional, as
# munin-node-configure won't recurse into subdirectories.
internManyPlugins = path:
"find '${path}' -type f -perm /a+x -exec cp -a -t . '{}' '+'";
internManyPlugins = path: "find '${path}' -type f -perm /a+x -exec cp -a -t . '{}' '+'";
# Use the appropriate intern-fn to copy the plugins into the store and patch
# them afterwards in an attempt to get them to run on NixOS.
@ -98,8 +98,9 @@ let
# For now we make the simplifying assumption that no file will contain lines
# which mix store paths and FHS paths, and thus run our substitution only on
# lines which do not contain store paths.
internAndFixPlugins = name: intern-fn: paths:
pkgs.runCommand name {} ''
internAndFixPlugins =
name: intern-fn: paths:
pkgs.runCommand name { } ''
mkdir -p "$out"
cd "$out"
${lib.concatStringsSep "\n" (map intern-fn paths)}
@ -112,14 +113,18 @@ let
# TODO: write a derivation for munin-contrib, so that for contrib plugins
# you can just refer to them by name rather than needing to include a copy
# of munin-contrib in your nixos configuration.
extraPluginDir = internAndFixPlugins "munin-extra-plugins.d"
internOnePlugin
(lib.attrsets.mapAttrsToList (k: v: { name = k; path = v; }) nodeCfg.extraPlugins);
extraPluginDir = internAndFixPlugins "munin-extra-plugins.d" internOnePlugin (
lib.attrsets.mapAttrsToList (k: v: {
name = k;
path = v;
}) nodeCfg.extraPlugins
);
extraAutoPluginDir = internAndFixPlugins "munin-extra-auto-plugins.d"
internManyPlugins nodeCfg.extraAutoPlugins;
extraAutoPluginDir =
internAndFixPlugins "munin-extra-auto-plugins.d" internManyPlugins
nodeCfg.extraAutoPlugins;
customStaticDir = pkgs.runCommand "munin-custom-static-data" {} ''
customStaticDir = pkgs.runCommand "munin-custom-static-data" { } ''
cp -a "${pkgs.munin}/etc/opt/munin/static" "$out"
cd "$out"
chmod -R u+w .
@ -168,7 +173,7 @@ in
};
extraPlugins = lib.mkOption {
default = {};
default = { };
type = with lib.types; attrsOf path;
description = ''
Additional Munin plugins to activate. Keys are the name of the plugin
@ -198,7 +203,7 @@ in
};
extraAutoPlugins = lib.mkOption {
default = [];
default = [ ];
type = with lib.types; listOf path;
description = ''
Additional Munin plugins to autoconfigure, using
@ -243,7 +248,10 @@ in
`/var/log/munin/munin-update.log` for timing
information, and the NixOS build of Munin does not write this file.
'';
example = [ "diskstats" "zfs_usage_*" ];
example = [
"diskstats"
"zfs_usage_*"
];
};
};
@ -314,100 +322,111 @@ in
};
config = lib.mkMerge [ (lib.mkIf (nodeCfg.enable || cronCfg.enable) {
config = lib.mkMerge [
(lib.mkIf (nodeCfg.enable || cronCfg.enable) {
environment.systemPackages = [ pkgs.munin ];
environment.systemPackages = [ pkgs.munin ];
users.users.munin = {
description = "Munin monitoring user";
group = "munin";
uid = config.ids.uids.munin;
home = "/var/lib/munin";
};
users.users.munin = {
description = "Munin monitoring user";
group = "munin";
uid = config.ids.uids.munin;
home = "/var/lib/munin";
};
users.groups.munin = {
gid = config.ids.gids.munin;
};
users.groups.munin = {
gid = config.ids.gids.munin;
};
}) (lib.mkIf nodeCfg.enable {
})
(lib.mkIf nodeCfg.enable {
systemd.services.munin-node = {
description = "Munin Node";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ munin smartmontools "/run/current-system/sw" "/run/wrappers" ];
environment.MUNIN_LIBDIR = "${pkgs.munin}/lib";
environment.MUNIN_PLUGSTATE = "/run/munin";
environment.MUNIN_LOGDIR = "/var/log/munin";
preStart = ''
echo "Updating munin plugins..."
systemd.services.munin-node = {
description = "Munin Node";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path = with pkgs; [
munin
smartmontools
"/run/current-system/sw"
"/run/wrappers"
];
environment.MUNIN_LIBDIR = "${pkgs.munin}/lib";
environment.MUNIN_PLUGSTATE = "/run/munin";
environment.MUNIN_LOGDIR = "/var/log/munin";
preStart = ''
echo "Updating munin plugins..."
mkdir -p /etc/munin/plugins
rm -rf /etc/munin/plugins/*
mkdir -p /etc/munin/plugins
rm -rf /etc/munin/plugins/*
# Autoconfigure builtin plugins
${pkgs.munin}/bin/munin-node-configure --suggest --shell --families contrib,auto,manual --config ${nodeConf} --libdir=${pkgs.munin}/lib/plugins --servicedir=/etc/munin/plugins --sconfdir=${pluginConfDir} 2>/dev/null | ${pkgs.bash}/bin/bash
# Autoconfigure builtin plugins
${pkgs.munin}/bin/munin-node-configure --suggest --shell --families contrib,auto,manual --config ${nodeConf} --libdir=${pkgs.munin}/lib/plugins --servicedir=/etc/munin/plugins --sconfdir=${pluginConfDir} 2>/dev/null | ${pkgs.bash}/bin/bash
# Autoconfigure extra plugins
${pkgs.munin}/bin/munin-node-configure --suggest --shell --families contrib,auto,manual --config ${nodeConf} --libdir=${extraAutoPluginDir} --servicedir=/etc/munin/plugins --sconfdir=${pluginConfDir} 2>/dev/null | ${pkgs.bash}/bin/bash
# Autoconfigure extra plugins
${pkgs.munin}/bin/munin-node-configure --suggest --shell --families contrib,auto,manual --config ${nodeConf} --libdir=${extraAutoPluginDir} --servicedir=/etc/munin/plugins --sconfdir=${pluginConfDir} 2>/dev/null | ${pkgs.bash}/bin/bash
${lib.optionalString (nodeCfg.extraPlugins != {}) ''
${lib.optionalString (nodeCfg.extraPlugins != { }) ''
# Link in manually enabled plugins
ln -f -s -t /etc/munin/plugins ${extraPluginDir}/*
''}
${lib.optionalString (nodeCfg.disabledPlugins != []) ''
${lib.optionalString (nodeCfg.disabledPlugins != [ ]) ''
# Disable plugins
cd /etc/munin/plugins
rm -f ${toString nodeCfg.disabledPlugins}
''}
'';
serviceConfig = {
ExecStart = "${pkgs.munin}/sbin/munin-node --config ${nodeConf} --servicedir /etc/munin/plugins/ --sconfdir=${pluginConfDir}";
'';
serviceConfig = {
ExecStart = "${pkgs.munin}/sbin/munin-node --config ${nodeConf} --servicedir /etc/munin/plugins/ --sconfdir=${pluginConfDir}";
};
};
};
# munin_stats plugin breaks as of 2.0.33 when this doesn't exist
systemd.tmpfiles.settings."10-munin"."/run/munin".d = {
mode = "0755";
user = "munin";
group = "munin";
};
}) (lib.mkIf cronCfg.enable {
# Munin is hardcoded to use DejaVu Mono and the graphs come out wrong if
# it's not available.
fonts.packages = [ pkgs.dejavu_fonts ];
systemd.timers.munin-cron = {
description = "batch Munin master programs";
wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = "*:0/5";
};
systemd.services.munin-cron = {
description = "batch Munin master programs";
unitConfig.Documentation = "man:munin-cron(8)";
serviceConfig = {
Type = "oneshot";
User = "munin";
ExecStart = "${pkgs.munin}/bin/munin-cron --config ${muninConf}";
};
};
systemd.tmpfiles.settings."20-munin" = let
defaultConfig = {
# munin_stats plugin breaks as of 2.0.33 when this doesn't exist
systemd.tmpfiles.settings."10-munin"."/run/munin".d = {
mode = "0755";
user = "munin";
group = "munin";
};
in {
"/run/munin".d = defaultConfig;
"/var/log/munin".d = defaultConfig;
"/var/www/munin".d = defaultConfig;
"/var/lib/munin".d = defaultConfig;
};
})];
})
(lib.mkIf cronCfg.enable {
# Munin is hardcoded to use DejaVu Mono and the graphs come out wrong if
# it's not available.
fonts.packages = [ pkgs.dejavu_fonts ];
systemd.timers.munin-cron = {
description = "batch Munin master programs";
wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = "*:0/5";
};
systemd.services.munin-cron = {
description = "batch Munin master programs";
unitConfig.Documentation = "man:munin-cron(8)";
serviceConfig = {
Type = "oneshot";
User = "munin";
ExecStart = "${pkgs.munin}/bin/munin-cron --config ${muninConf}";
};
};
systemd.tmpfiles.settings."20-munin" =
let
defaultConfig = {
mode = "0755";
user = "munin";
group = "munin";
};
in
{
"/run/munin".d = defaultConfig;
"/var/log/munin".d = defaultConfig;
"/var/www/munin".d = defaultConfig;
"/var/lib/munin".d = defaultConfig;
};
})
];
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.ocsinventory-agent;
@ -98,7 +103,8 @@ in
let
configFile = settingsFormat.generate "ocsinventory-agent.cfg" cfg.settings;
in lib.mkIf cfg.enable {
in
lib.mkIf cfg.enable {
# Path of the configuration file is hard-coded and cannot be changed
# https://github.com/OCSInventory-NG/UnixAgent/blob/v2.10.0/lib/Ocsinventory/Agent/Config.pm#L78
#

View file

@ -1,7 +1,19 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkEnableOption mkPackageOption mkIf mkOption types getExe;
inherit (lib)
mkEnableOption
mkPackageOption
mkIf
mkOption
types
getExe
;
cfg = config.services.opentelemetry-collector;
opentelemetry-collector = cfg.package;
@ -34,16 +46,16 @@ in
};
config = mkIf cfg.enable {
assertions = [{
assertion = (
(cfg.settings == { }) != (cfg.configFile == null)
);
message = ''
Please specify a configuration for Opentelemetry Collector with either
'services.opentelemetry-collector.settings' or
'services.opentelemetry-collector.configFile'.
'';
}];
assertions = [
{
assertion = ((cfg.settings == { }) != (cfg.configFile == null));
message = ''
Please specify a configuration for Opentelemetry Collector with either
'services.opentelemetry-collector.settings' or
'services.opentelemetry-collector.configFile'.
'';
}
];
systemd.services.opentelemetry-collector = {
description = "Opentelemetry Collector Service Daemon";
@ -52,9 +64,10 @@ in
serviceConfig =
let
conf =
if cfg.configFile == null
then settingsFormat.generate "config.yaml" cfg.settings
else cfg.configFile;
if cfg.configFile == null then
settingsFormat.generate "config.yaml" cfg.settings
else
cfg.configFile;
in
{
ExecStart = "${getExe opentelemetry-collector} --config=file:${conf}";

View file

@ -1,8 +1,16 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.osquery;
dirname = path: with lib.strings; with lib.lists; concatStringsSep "/"
(init (splitString "/" (normalizePath path)));
dirname =
path:
with lib.strings;
with lib.lists;
concatStringsSep "/" (init (splitString "/" (normalizePath path)));
# conf is the osquery configuration file used when the --config_plugin=filesystem.
# filesystem is the osquery default value for the config_plugin flag.
@ -10,11 +18,13 @@ let
# flagfile is the file containing osquery command line flags to be
# provided to the application using the special --flagfile option.
flagfile = pkgs.writeText "osquery.flags"
(lib.concatStringsSep "\n"
(lib.mapAttrsToList (name: value: "--${name}=${value}")
flagfile = pkgs.writeText "osquery.flags" (
lib.concatStringsSep "\n" (
lib.mapAttrsToList (name: value: "--${name}=${value}")
# Use the conf derivation if not otherwise specified.
({ config_path = conf; } // cfg.flags)));
({ config_path = conf; } // cfg.flags)
)
);
osqueryi = pkgs.runCommand "osqueryi" { nativeBuildInputs = [ pkgs.makeWrapper ]; } ''
mkdir -p $out/bin
@ -47,7 +57,8 @@ in
example = {
config_refresh = "10";
};
type = with lib.types;
type =
with lib.types;
submodule {
freeformType = attrsOf str;
options = {
@ -77,7 +88,10 @@ in
config = lib.mkIf cfg.enable {
environment.systemPackages = [ osqueryi ];
systemd.services.osqueryd = {
after = [ "network.target" "syslog.service" ];
after = [
"network.target"
"syslog.service"
];
description = "The osquery daemon";
serviceConfig = {
ExecStart = "${pkgs.osquery}/bin/osqueryd --flagfile ${flagfile}";

View file

@ -1,4 +1,10 @@
{ config, lib, options, pkgs, ... }:
{
config,
lib,
options,
pkgs,
...
}:
let
cfg = config.services.parsedmarc;
@ -6,16 +12,31 @@ let
isSecret = v: isAttrs v && v ? _secret && isString v._secret;
ini = pkgs.formats.ini {
mkKeyValue = lib.flip lib.generators.mkKeyValueDefault "=" rec {
mkValueString = v:
if isInt v then toString v
else if isString v then v
else if true == v then "True"
else if false == v then "False"
else if isSecret v then hashString "sha256" v._secret
else throw "unsupported type ${typeOf v}: ${(lib.generators.toPretty {}) v}";
mkValueString =
v:
if isInt v then
toString v
else if isString v then
v
else if true == v then
"True"
else if false == v then
"False"
else if isSecret v then
hashString "sha256" v._secret
else
throw "unsupported type ${typeOf v}: ${(lib.generators.toPretty { }) v}";
};
};
inherit (builtins) elem isAttrs isString isInt isList typeOf hashString;
inherit (builtins)
elem
isAttrs
isString
isInt
isList
typeOf
hashString
;
in
{
options.services.parsedmarc = {
@ -301,15 +322,15 @@ in
description = ''
The addresses to send outgoing mail to.
'';
apply = x: if x == [] || x == null then null else lib.concatStringsSep "," x;
apply = x: if x == [ ] || x == null then null else lib.concatStringsSep "," x;
};
};
elasticsearch = {
hosts = lib.mkOption {
default = [];
default = [ ];
type = with lib.types; listOf str;
apply = x: if x == [] then null else lib.concatStringsSep "," x;
apply = x: if x == [ ] then null else lib.concatStringsSep "," x;
description = ''
A list of Elasticsearch hosts to push parsed reports
to.
@ -366,12 +387,23 @@ in
config = lib.mkIf cfg.enable {
warnings = let
deprecationWarning = optname: "Starting in 8.0.0, the `${optname}` option has been moved from the `services.parsedmarc.settings.imap`"
+ "configuration section to the `services.parsedmarc.settings.mailbox` configuration section.";
hasImapOpt = lib.flip builtins.hasAttr cfg.settings.imap;
movedOptions = [ "reports_folder" "archive_folder" "watch" "delete" "test" "batch_size" ];
in builtins.map deprecationWarning (builtins.filter hasImapOpt movedOptions);
warnings =
let
deprecationWarning =
optname:
"Starting in 8.0.0, the `${optname}` option has been moved from the `services.parsedmarc.settings.imap`"
+ "configuration section to the `services.parsedmarc.settings.mailbox` configuration section.";
hasImapOpt = lib.flip builtins.hasAttr cfg.settings.imap;
movedOptions = [
"reports_folder"
"archive_folder"
"watch"
"delete"
"test"
"batch_size"
];
in
builtins.map deprecationWarning (builtins.filter hasImapOpt movedOptions);
services.elasticsearch.enable = lib.mkDefault cfg.provision.elasticsearch;
@ -402,7 +434,8 @@ in
};
services.grafana = {
declarativePlugins = with pkgs.grafanaPlugins;
declarativePlugins =
with pkgs.grafanaPlugins;
lib.mkIf cfg.provision.grafana.dashboard [
grafana-worldmap-panel
grafana-piechart-panel
@ -414,32 +447,34 @@ in
let
esVersion = lib.getVersion config.services.elasticsearch.package;
in
lib.mkIf cfg.provision.grafana.datasource [
{
name = "dmarc-ag";
type = "elasticsearch";
access = "proxy";
url = "http://localhost:9200";
jsonData = {
timeField = "date_range";
inherit esVersion;
};
}
{
name = "dmarc-fo";
type = "elasticsearch";
access = "proxy";
url = "http://localhost:9200";
jsonData = {
timeField = "date_range";
inherit esVersion;
};
}
];
dashboards.settings.providers = lib.mkIf cfg.provision.grafana.dashboard [{
name = "parsedmarc";
options.path = "${pkgs.parsedmarc.dashboard}";
}];
lib.mkIf cfg.provision.grafana.datasource [
{
name = "dmarc-ag";
type = "elasticsearch";
access = "proxy";
url = "http://localhost:9200";
jsonData = {
timeField = "date_range";
inherit esVersion;
};
}
{
name = "dmarc-fo";
type = "elasticsearch";
access = "proxy";
url = "http://localhost:9200";
jsonData = {
timeField = "date_range";
inherit esVersion;
};
}
];
dashboards.settings.providers = lib.mkIf cfg.provision.grafana.dashboard [
{
name = "parsedmarc";
options.path = "${pkgs.parsedmarc.dashboard}";
}
];
};
};
@ -470,7 +505,14 @@ in
# lists, empty attrsets and null. This makes it possible to
# list interesting options in `settings` without them always
# ending up in the resulting config.
filteredConfig = lib.converge (lib.filterAttrsRecursive (_: v: ! elem v [ null [] {} ])) cfg.settings;
filteredConfig = lib.converge (lib.filterAttrsRecursive (
_: v:
!elem v [
null
[ ]
{ }
]
)) cfg.settings;
# Extract secrets (attributes set to an attrset with a
# "_secret" key) from the settings and generate the commands
@ -478,61 +520,86 @@ in
secretPaths = lib.catAttrs "_secret" (lib.collect isSecret filteredConfig);
parsedmarcConfig = ini.generate "parsedmarc.ini" filteredConfig;
mkSecretReplacement = file: ''
replace-secret ${lib.escapeShellArgs [ (hashString "sha256" file) file "/run/parsedmarc/parsedmarc.ini" ]}
replace-secret ${
lib.escapeShellArgs [
(hashString "sha256" file)
file
"/run/parsedmarc/parsedmarc.ini"
]
}
'';
secretReplacements = lib.concatMapStrings mkSecretReplacement secretPaths;
in
{
wantedBy = [ "multi-user.target" ];
after = [ "postfix.service" "dovecot2.service" "elasticsearch.service" ];
path = with pkgs; [ replace-secret openssl shadow ];
serviceConfig = {
ExecStartPre = let
startPreFullPrivileges = ''
set -o errexit -o pipefail -o nounset -o errtrace
shopt -s inherit_errexit
{
wantedBy = [ "multi-user.target" ];
after = [
"postfix.service"
"dovecot2.service"
"elasticsearch.service"
];
path = with pkgs; [
replace-secret
openssl
shadow
];
serviceConfig = {
ExecStartPre =
let
startPreFullPrivileges =
''
set -o errexit -o pipefail -o nounset -o errtrace
shopt -s inherit_errexit
umask u=rwx,g=,o=
cp ${parsedmarcConfig} /run/parsedmarc/parsedmarc.ini
chown parsedmarc:parsedmarc /run/parsedmarc/parsedmarc.ini
${secretReplacements}
'' + lib.optionalString cfg.provision.localMail.enable ''
openssl rand -hex 64 >/run/parsedmarc/dmarc_user_passwd
replace-secret '@imap-password@' '/run/parsedmarc/dmarc_user_passwd' /run/parsedmarc/parsedmarc.ini
echo "Setting new randomized password for user '${cfg.provision.localMail.recipientName}'."
cat <(echo -n "${cfg.provision.localMail.recipientName}:") /run/parsedmarc/dmarc_user_passwd | chpasswd
'';
umask u=rwx,g=,o=
cp ${parsedmarcConfig} /run/parsedmarc/parsedmarc.ini
chown parsedmarc:parsedmarc /run/parsedmarc/parsedmarc.ini
${secretReplacements}
''
+ lib.optionalString cfg.provision.localMail.enable ''
openssl rand -hex 64 >/run/parsedmarc/dmarc_user_passwd
replace-secret '@imap-password@' '/run/parsedmarc/dmarc_user_passwd' /run/parsedmarc/parsedmarc.ini
echo "Setting new randomized password for user '${cfg.provision.localMail.recipientName}'."
cat <(echo -n "${cfg.provision.localMail.recipientName}:") /run/parsedmarc/dmarc_user_passwd | chpasswd
'';
in
"+${pkgs.writeShellScript "parsedmarc-start-pre-full-privileges" startPreFullPrivileges}";
Type = "simple";
User = "parsedmarc";
Group = "parsedmarc";
DynamicUser = true;
RuntimeDirectory = "parsedmarc";
RuntimeDirectoryMode = "0700";
CapabilityBoundingSet = "";
PrivateDevices = true;
PrivateMounts = true;
PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProcSubset = "pid";
SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ];
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
RestrictRealtime = true;
RestrictNamespaces = true;
MemoryDenyWriteExecute = true;
LockPersonality = true;
SystemCallArchitectures = "native";
ExecStart = "${lib.getExe pkgs.parsedmarc} -c /run/parsedmarc/parsedmarc.ini";
};
"+${pkgs.writeShellScript "parsedmarc-start-pre-full-privileges" startPreFullPrivileges}";
Type = "simple";
User = "parsedmarc";
Group = "parsedmarc";
DynamicUser = true;
RuntimeDirectory = "parsedmarc";
RuntimeDirectoryMode = "0700";
CapabilityBoundingSet = "";
PrivateDevices = true;
PrivateMounts = true;
PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProcSubset = "pid";
SystemCallFilter = [
"@system-service"
"~@privileged"
"~@resources"
];
RestrictAddressFamilies = [
"AF_UNIX"
"AF_INET"
"AF_INET6"
];
RestrictRealtime = true;
RestrictNamespaces = true;
MemoryDenyWriteExecute = true;
LockPersonality = true;
SystemCallArchitectures = "native";
ExecStart = "${lib.getExe pkgs.parsedmarc} -c /run/parsedmarc/parsedmarc.ini";
};
};
users.users.${cfg.provision.localMail.recipientName} = lib.mkIf cfg.provision.localMail.enable {
isNormalUser = true;

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.prometheus.alertmanagerWebhookLogger;
in
@ -10,7 +15,7 @@ in
extraFlags = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
default = [ ];
description = "Extra command line options to pass to alertmanager-webhook-logger.";
};
};
@ -55,9 +60,12 @@ in
ProtectKernelLogs = true;
ProtectControlGroups = true;
Restart = "on-failure";
Restart = "on-failure";
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;

View file

@ -1,36 +1,50 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.prometheus.alertmanager;
mkConfigFile = pkgs.writeText "alertmanager.yml" (builtins.toJSON cfg.configuration);
checkedConfig = file:
checkedConfig =
file:
if cfg.checkConfig then
pkgs.runCommand "checked-config" { nativeBuildInputs = [ cfg.package ]; } ''
ln -s ${file} $out
amtool check-config $out
'' else file;
''
else
file;
alertmanagerYml = let
yml = if cfg.configText != null then
pkgs.writeText "alertmanager.yml" cfg.configText
else mkConfigFile;
in checkedConfig yml;
alertmanagerYml =
let
yml =
if cfg.configText != null then pkgs.writeText "alertmanager.yml" cfg.configText else mkConfigFile;
in
checkedConfig yml;
cmdlineArgs = cfg.extraFlags ++ [
"--config.file /tmp/alert-manager-substituted.yaml"
"--web.listen-address ${cfg.listenAddress}:${toString cfg.port}"
"--log.level ${cfg.logLevel}"
"--storage.path /var/lib/alertmanager"
(toString (map (peer: "--cluster.peer ${peer}:9094") cfg.clusterPeers))
] ++ (lib.optional (cfg.webExternalUrl != null)
"--web.external-url ${cfg.webExternalUrl}"
) ++ (lib.optional (cfg.logFormat != null)
"--log.format ${cfg.logFormat}"
);
in {
cmdlineArgs =
cfg.extraFlags
++ [
"--config.file /tmp/alert-manager-substituted.yaml"
"--web.listen-address ${cfg.listenAddress}:${toString cfg.port}"
"--log.level ${cfg.logLevel}"
"--storage.path /var/lib/alertmanager"
(toString (map (peer: "--cluster.peer ${peer}:9094") cfg.clusterPeers))
]
++ (lib.optional (cfg.webExternalUrl != null) "--web.external-url ${cfg.webExternalUrl}")
++ (lib.optional (cfg.logFormat != null) "--log.format ${cfg.logFormat}");
in
{
imports = [
(lib.mkRemovedOptionModule [ "services" "prometheus" "alertmanager" "user" ] "The alertmanager service is now using systemd's DynamicUser mechanism which obviates a user setting.")
(lib.mkRemovedOptionModule [ "services" "prometheus" "alertmanager" "group" ] "The alertmanager service is now using systemd's DynamicUser mechanism which obviates a group setting.")
(lib.mkRemovedOptionModule [ "services" "prometheus" "alertmanager" "user" ]
"The alertmanager service is now using systemd's DynamicUser mechanism which obviates a user setting."
)
(lib.mkRemovedOptionModule [ "services" "prometheus" "alertmanager" "group" ]
"The alertmanager service is now using systemd's DynamicUser mechanism which obviates a group setting."
)
(lib.mkRemovedOptionModule [ "services" "prometheus" "alertmanagerURL" ] ''
Due to incompatibility, the alertmanagerURL option has been removed,
please use 'services.prometheus.alertmanagers' instead.
@ -91,7 +105,13 @@ in {
};
logLevel = lib.mkOption {
type = lib.types.enum ["debug" "info" "warn" "error" "fatal"];
type = lib.types.enum [
"debug"
"info"
"warn"
"error"
"fatal"
];
default = "warn";
description = ''
Only log messages with the given severity or above.
@ -136,7 +156,7 @@ in {
clusterPeers = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
default = [ ];
description = ''
Initial peers for HA cluster.
'';
@ -144,7 +164,7 @@ in {
extraFlags = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
default = [ ];
description = ''
Extra commandline options when launching the Alertmanager.
'';
@ -168,8 +188,9 @@ in {
(lib.mkIf cfg.enable {
assertions = lib.singleton {
assertion = cfg.configuration != null || cfg.configText != null;
message = "Can not enable alertmanager without a configuration. "
+ "Set either the `configuration` or `configText` attribute.";
message =
"Can not enable alertmanager without a configuration. "
+ "Set either the `configuration` or `configText` attribute.";
};
})
(lib.mkIf cfg.enable {
@ -177,16 +198,18 @@ in {
systemd.services.alertmanager = {
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
preStart = ''
${lib.getBin pkgs.envsubst}/bin/envsubst -o "/tmp/alert-manager-substituted.yaml" \
-i "${alertmanagerYml}"
${lib.getBin pkgs.envsubst}/bin/envsubst -o "/tmp/alert-manager-substituted.yaml" \
-i "${alertmanagerYml}"
'';
serviceConfig = {
ExecStart = "${cfg.package}/bin/alertmanager" +
lib.optionalString (lib.length cmdlineArgs != 0) (" \\\n " +
lib.concatStringsSep " \\\n " cmdlineArgs);
ExecStart =
"${cfg.package}/bin/alertmanager"
+ lib.optionalString (lib.length cmdlineArgs != 0) (
" \\\n " + lib.concatStringsSep " \\\n " cmdlineArgs
);
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
@ -217,9 +240,13 @@ in {
ProtectKernelLogs = true;
ProtectControlGroups = true;
Restart = "always";
Restart = "always";
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_NETLINK" ];
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.apcupsd;
@ -16,7 +22,11 @@ in
};
apcupsdNetwork = mkOption {
type = types.enum ["tcp" "tcp4" "tcp6"];
type = types.enum [
"tcp"
"tcp4"
"tcp6"
];
default = "tcp";
description = ''
Network of the apcupsd Network Information Server (NIS): one of "tcp", "tcp4", or "tcp6".

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.artifactory;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.bind;
@ -22,15 +28,28 @@ in
'';
};
bindVersion = mkOption {
type = types.enum [ "xml.v2" "xml.v3" "auto" ];
type = types.enum [
"xml.v2"
"xml.v3"
"auto"
];
default = "auto";
description = ''
BIND statistics version. Can be detected automatically.
'';
};
bindGroups = mkOption {
type = types.listOf (types.enum [ "server" "view" "tasks" ]);
default = [ "server" "view" ];
type = types.listOf (
types.enum [
"server"
"view"
"tasks"
]
);
default = [
"server"
"view"
];
description = ''
List of statistics to collect. Available: [server, view, tasks]
'';

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.bird;
@ -13,7 +19,10 @@ in
port = 9324;
extraOpts = {
birdVersion = mkOption {
type = types.enum [ 1 2 ];
type = types.enum [
1
2
];
default = 2;
description = ''
Specifies whether BIRD1 or BIRD2 is in use.

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.bitcoin;
@ -25,7 +31,10 @@ in
};
rpcScheme = mkOption {
type = types.enum [ "http" "https" ];
type = types.enum [
"http"
"https"
];
default = "http";
description = ''
Whether to connect to bitcoind over http or https.
@ -58,7 +67,7 @@ in
extraEnv = mkOption {
type = types.attrsOf types.str;
default = {};
default = { };
description = ''
Extra environment variables for the exporter.
'';

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
logPrefix = "services.prometheus.exporter.blackbox";
@ -12,29 +18,37 @@ let
# This ensures that we can deal with string paths, path types and
# store-path strings with context.
coerceConfigFile = file:
coerceConfigFile =
file:
if (builtins.isPath file) || (lib.isStorePath file) then
file
else
(lib.warn ''
${logPrefix}: configuration file "${file}" is being copied to the nix-store.
If you would like to avoid that, please set enableConfigCheck to false.
'' /. + file);
checkConfigLocation = file:
(
lib.warn ''
${logPrefix}: configuration file "${file}" is being copied to the nix-store.
If you would like to avoid that, please set enableConfigCheck to false.
'' /.
+ file
);
checkConfigLocation =
file:
if lib.hasPrefix "/tmp/" file then
throw
"${logPrefix}: configuration file must not reside within /tmp - it won't be visible to the systemd service."
throw "${logPrefix}: configuration file must not reside within /tmp - it won't be visible to the systemd service."
else
file;
checkConfig = file:
pkgs.runCommand "checked-blackbox-exporter.conf" {
preferLocalBuild = true;
nativeBuildInputs = [ pkgs.buildPackages.prometheus-blackbox-exporter ];
} ''
ln -s ${coerceConfigFile file} $out
blackbox_exporter --config.check --config.file $out
'';
in {
checkConfig =
file:
pkgs.runCommand "checked-blackbox-exporter.conf"
{
preferLocalBuild = true;
nativeBuildInputs = [ pkgs.buildPackages.prometheus-blackbox-exporter ];
}
''
ln -s ${coerceConfigFile file} $out
blackbox_exporter --config.check --config.file $out
'';
in
{
port = 9115;
extraOpts = {
configFile = mkOption {
@ -54,21 +68,21 @@ in {
};
};
serviceOpts = let
adjustedConfigFile = if cfg.enableConfigCheck then
checkConfig cfg.configFile
else
checkConfigLocation cfg.configFile;
in {
serviceConfig = {
AmbientCapabilities = [ "CAP_NET_RAW" ]; # for ping probes
ExecStart = ''
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--config.file ${escapeShellArg adjustedConfigFile} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
serviceOpts =
let
adjustedConfigFile =
if cfg.enableConfigCheck then checkConfig cfg.configFile else checkConfigLocation cfg.configFile;
in
{
serviceConfig = {
AmbientCapabilities = [ "CAP_NET_RAW" ]; # for ping probes
ExecStart = ''
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--config.file ${escapeShellArg adjustedConfigFile} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
};
};
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.buildkite-agent;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.collectd;
@ -34,11 +40,15 @@ in
default = "0.0.0.0";
description = ''
Address to listen on for binary network packets.
'';
'';
};
securityLevel = mkOption {
type = types.enum ["None" "Sign" "Encrypt"];
type = types.enum [
"None"
"Sign"
"Encrypt"
];
default = "None";
description = ''
Minimum required security level for accepted packets.
@ -47,7 +57,10 @@ in
};
logFormat = mkOption {
type = types.enum [ "logfmt" "json" ];
type = types.enum [
"logfmt"
"json"
];
default = "logfmt";
example = "json";
description = ''
@ -56,28 +69,36 @@ in
};
logLevel = mkOption {
type = types.enum ["debug" "info" "warn" "error" "fatal"];
type = types.enum [
"debug"
"info"
"warn"
"error"
"fatal"
];
default = "info";
description = ''
Only log messages with the given severity or above.
'';
};
};
serviceOpts = let
collectSettingsArgs = optionalString (cfg.collectdBinary.enable) ''
--collectd.listen-address ${cfg.collectdBinary.listenAddress}:${toString cfg.collectdBinary.port} \
--collectd.security-level ${cfg.collectdBinary.securityLevel} \
'';
in {
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-collectd-exporter}/bin/collectd_exporter \
--log.format ${escapeShellArg cfg.logFormat} \
--log.level ${cfg.logLevel} \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
${collectSettingsArgs} \
${concatStringsSep " \\\n " cfg.extraFlags}
serviceOpts =
let
collectSettingsArgs = optionalString (cfg.collectdBinary.enable) ''
--collectd.listen-address ${cfg.collectdBinary.listenAddress}:${toString cfg.collectdBinary.port} \
--collectd.security-level ${cfg.collectdBinary.securityLevel} \
'';
in
{
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-collectd-exporter}/bin/collectd_exporter \
--log.format ${escapeShellArg cfg.logFormat} \
--log.level ${cfg.logLevel} \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
${collectSettingsArgs} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.prometheus.exporters.deluge;
@ -67,19 +72,24 @@ in
ExecStart = ''
${pkgs.prometheus-deluge-exporter}/bin/deluge-exporter
'';
Environment = [
"LISTEN_PORT=${toString cfg.port}"
"LISTEN_ADDRESS=${toString cfg.listenAddress}"
Environment =
[
"LISTEN_PORT=${toString cfg.port}"
"LISTEN_ADDRESS=${toString cfg.listenAddress}"
"DELUGE_HOST=${cfg.delugeHost}"
"DELUGE_USER=${cfg.delugeUser}"
"DELUGE_PORT=${toString cfg.delugePort}"
] ++ lib.optionals (cfg.delugePassword != null) [
"DELUGE_PASSWORD=${cfg.delugePassword}"
] ++ lib.optionals cfg.exportPerTorrentMetrics [
"PER_TORRENT_METRICS=1"
];
EnvironmentFile = lib.optionalString (cfg.delugePasswordFile != null) "/etc/deluge-exporter/password";
"DELUGE_HOST=${cfg.delugeHost}"
"DELUGE_USER=${cfg.delugeUser}"
"DELUGE_PORT=${toString cfg.delugePort}"
]
++ lib.optionals (cfg.delugePassword != null) [
"DELUGE_PASSWORD=${cfg.delugePassword}"
]
++ lib.optionals cfg.exportPerTorrentMetrics [
"PER_TORRENT_METRICS=1"
];
EnvironmentFile = lib.optionalString (
cfg.delugePasswordFile != null
) "/etc/deluge-exporter/password";
};
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.dmarc;
@ -8,7 +14,10 @@ let
inherit (cfg) folders port;
listen_addr = cfg.listenAddress;
storage_path = "$STATE_DIRECTORY";
imap = (builtins.removeAttrs cfg.imap [ "passwordFile" ]) // { password = "$IMAP_PASSWORD"; use_ssl = true; };
imap = (builtins.removeAttrs cfg.imap [ "passwordFile" ]) // {
password = "$IMAP_PASSWORD";
use_ssl = true;
};
poll_interval_seconds = cfg.pollIntervalSeconds;
deduplication_max_seconds = cfg.deduplicationMaxSeconds;
logging = {
@ -16,7 +25,8 @@ let
disable_existing_loggers = false;
};
};
in {
in
{
port = 9797;
extraOpts = {
imap = {
@ -97,7 +107,10 @@ in {
};
};
serviceOpts = {
path = with pkgs; [ envsubst coreutils ];
path = with pkgs; [
envsubst
coreutils
];
serviceConfig = {
StateDirectory = "prometheus-dmarc-exporter";
WorkingDirectory = "/var/lib/prometheus-dmarc-exporter";

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.dnsmasq;

View file

@ -1,9 +1,15 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.prometheus.exporters.dnssec;
configFormat = pkgs.formats.toml { };
configFile = configFormat.generate "dnssec-checks.toml" cfg.configuration;
in {
in
{
port = 9204;
extraOpts = {
configuration = lib.mkOption {
@ -70,21 +76,26 @@ in {
};
serviceOpts = {
serviceConfig = let
startScript = pkgs.writeShellScriptBin "prometheus-dnssec-exporter-start"
"${lib.concatStringsSep " "
([ "${pkgs.prometheus-dnssec-exporter}/bin/prometheus-dnssec-exporter" ]
++ lib.optionals (cfg.configuration != null)
[ "-config ${configFile}" ]
++ lib.optionals (cfg.listenAddress != null)
[ "-listen-address ${lib.escapeShellArg cfg.listenAddress}" ]
++ lib.optionals (cfg.resolvers != [ ]) [
"-resolvers ${
lib.escapeShellArg (lib.concatStringsSep "," cfg.resolvers)
}"
] ++ lib.optionals (cfg.timeout != null)
[ "-timeout ${lib.escapeShellArg cfg.timeout}" ] ++ cfg.extraFlags)}";
in { ExecStart = lib.getExe startScript; };
serviceConfig =
let
startScript = pkgs.writeShellScriptBin "prometheus-dnssec-exporter-start" "${lib.concatStringsSep
" "
(
[ "${pkgs.prometheus-dnssec-exporter}/bin/prometheus-dnssec-exporter" ]
++ lib.optionals (cfg.configuration != null) [ "-config ${configFile}" ]
++ lib.optionals (cfg.listenAddress != null) [
"-listen-address ${lib.escapeShellArg cfg.listenAddress}"
]
++ lib.optionals (cfg.resolvers != [ ]) [
"-resolvers ${lib.escapeShellArg (lib.concatStringsSep "," cfg.resolvers)}"
]
++ lib.optionals (cfg.timeout != null) [ "-timeout ${lib.escapeShellArg cfg.timeout}" ]
++ cfg.extraFlags
)
}";
in
{
ExecStart = lib.getExe startScript;
};
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.domain;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.dovecot;
@ -70,7 +76,10 @@ in
scopes = mkOption {
type = types.listOf types.str;
default = [ "user" ];
example = [ "user" "global" ];
example = [
"user"
"global"
];
description = ''
Stats scopes to query.
'';

View file

@ -1,10 +1,15 @@
{ config, lib, pkgs, options, type, ... }:
{
config,
lib,
pkgs,
options,
type,
...
}:
let
cfg = config.services.prometheus.exporters."exportarr-${type}";
exportarrEnvironment = (
lib.mapAttrs (_: toString) cfg.environment
) // {
exportarrEnvironment = (lib.mapAttrs (_: toString) cfg.environment) // {
PORT = toString cfg.port;
URL = cfg.url;
API_KEY_FILE = lib.mkIf (cfg.apiKeyFile != null) "%d/api-key";
@ -48,7 +53,10 @@ in
ExecStart = ''${cfg.package}/bin/exportarr ${type} "$@"'';
ProcSubset = "pid";
ProtectProc = "invisible";
SystemCallFilter = ["@system-service" "~@privileged"];
SystemCallFilter = [
"@system-service"
"~@privileged"
];
};
environment = exportarrEnvironment;
};

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.flow;
@ -9,7 +15,8 @@ let
concatStringsSep
optionalString
;
in {
in
{
port = 9590;
extraOpts = {
brokers = mkOption {
@ -26,7 +33,7 @@ in {
partitions = mkOption {
type = types.listOf types.int;
default = [];
default = [ ];
description = ''
The number of the partitions to consume, none means all.
'';
@ -47,7 +54,7 @@ in {
-asn ${toString cfg.asn} \
-topic ${cfg.topic} \
-brokers ${concatStringsSep "," cfg.brokers} \
${optionalString (cfg.partitions != []) "-partitions ${concatStringsSep "," cfg.partitions}"} \
${optionalString (cfg.partitions != [ ]) "-partitions ${concatStringsSep "," cfg.partitions}"} \
-addr ${cfg.listenAddress}:${toString cfg.port} ${concatStringsSep " " cfg.extraFlags}
'';
};

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, utils, ... }:
{
config,
lib,
pkgs,
utils,
...
}:
let
inherit (lib) mkOption types;
cfg = config.services.prometheus.exporters.fritz;
@ -30,55 +36,63 @@ in
visible = false;
};
log_level = mkOption {
type = types.enum [ "DEBUG" "INFO" "WARNING" "ERROR" "CRITICAL" ];
type = types.enum [
"DEBUG"
"INFO"
"WARNING"
"ERROR"
"CRITICAL"
];
default = "INFO";
description = ''
Log level to use for the exporter.
'';
};
devices = mkOption {
default = [];
default = [ ];
description = "Fritz!-devices to monitor using the exporter.";
type = with types; listOf (submodule {
freeformType = yaml.type;
type =
with types;
listOf (submodule {
freeformType = yaml.type;
options = {
name = mkOption {
type = types.str;
default = "";
description = ''
Name to use for the device.
'';
options = {
name = mkOption {
type = types.str;
default = "";
description = ''
Name to use for the device.
'';
};
hostname = mkOption {
type = types.str;
default = "fritz.box";
description = ''
Hostname under which the target device is reachable.
'';
};
username = mkOption {
type = types.str;
description = ''
Username to authenticate with the target device.
'';
};
password_file = mkOption {
type = types.path;
description = ''
Path to a file which contains the password to authenticate with the target device.
Needs to be readable by the user the exporter runs under.
'';
};
host_info = mkOption {
type = types.bool;
description = ''
Enable extended host info for this device. *Warning*: This will heavily increase scrape time.
'';
default = false;
};
};
hostname = mkOption {
type = types.str;
default = "fritz.box";
description = ''
Hostname under which the target device is reachable.
'';
};
username = mkOption {
type = types.str;
description = ''
Username to authenticate with the target device.
'';
};
password_file = mkOption {
type = types.path;
description = ''
Path to a file which contains the password to authenticate with the target device.
Needs to be readable by the user the exporter runs under.
'';
};
host_info = mkOption {
type = types.bool;
description = ''
Enable extended host info for this device. *Warning*: This will heavily increase scrape time.
'';
default = false;
};
};
});
});
};
};
};
@ -87,10 +101,14 @@ in
serviceOpts = {
serviceConfig = {
ExecStart = utils.escapeSystemdExecArgs ([
(lib.getExe pkgs.fritz-exporter)
"--config" configFile
] ++ cfg.extraFlags);
ExecStart = utils.escapeSystemdExecArgs (
[
(lib.getExe pkgs.fritz-exporter)
"--config"
configFile
]
++ cfg.extraFlags
);
DynamicUser = false;
};
};

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.fritzbox;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.graphite;

View file

@ -1,12 +1,20 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.idrac;
inherit (lib) mkOption types;
configFile = if cfg.configurationPath != null
then cfg.configurationPath
else pkgs.writeText "idrac.yml" (builtins.toJSON cfg.configuration);
configFile =
if cfg.configurationPath != null then
cfg.configurationPath
else
pkgs.writeText "idrac.yml" (builtins.toJSON cfg.configuration);
in
{
port = 9348;

View file

@ -1,16 +1,29 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.imap-mailstat;
valueToString = value:
if (builtins.typeOf value == "string") then "\"${value}\""
else (
if (builtins.typeOf value == "int") then "${toString value}"
else (
if (builtins.typeOf value == "bool") then (if value then "true" else "false")
else "XXX ${toString value}"
)
);
valueToString =
value:
if (builtins.typeOf value == "string") then
"\"${value}\""
else
(
if (builtins.typeOf value == "int") then
"${toString value}"
else
(
if (builtins.typeOf value == "bool") then
(if value then "true" else "false")
else
"XXX ${toString value}"
)
);
inherit (lib)
mkOption
types
@ -20,17 +33,29 @@ let
mapAttrs
optionalString
;
createConfigFile = accounts:
createConfigFile =
accounts:
# unfortunately on toTOML yet
# https://github.com/NixOS/nix/issues/3929
pkgs.writeText "imap-mailstat-exporter.conf" ''
${concatStrings (attrValues (mapAttrs (name: config: "[[Accounts]]\nname = \"${name}\"\n${concatStrings (attrValues (mapAttrs (k: v: "${k} = ${valueToString v}\n") config))}") accounts))}
${concatStrings (
attrValues (
mapAttrs (
name: config:
"[[Accounts]]\nname = \"${name}\"\n${
concatStrings (attrValues (mapAttrs (k: v: "${k} = ${valueToString v}\n") config))
}"
) accounts
)
)}
'';
mkOpt = type: description: mkOption {
type = types.nullOr type;
default = null;
description = description;
};
mkOpt =
type: description:
mkOption {
type = types.nullOr type;
default = null;
description = description;
};
accountOptions.options = {
mailaddress = mkOpt types.str "Your email address (at the moment used as login name)";
username = mkOpt types.str "If empty string mailaddress value is used";
@ -52,7 +77,7 @@ in
};
accounts = mkOption {
type = types.attrsOf (types.submodule accountOptions);
default = {};
default = { };
description = ''
Accounts to monitor
'';

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.influxdb;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
logPrefix = "services.prometheus.exporter.ipmi";
@ -10,7 +16,8 @@ let
optionals
escapeShellArg
;
in {
in
{
port = 9290;
extraOpts = {
@ -32,16 +39,27 @@ in {
};
serviceOpts.serviceConfig = {
ExecStart = with cfg; concatStringsSep " " ([
"${pkgs.prometheus-ipmi-exporter}/bin/ipmi_exporter"
"--web.listen-address ${listenAddress}:${toString port}"
] ++ optionals (cfg.webConfigFile != null) [
"--web.config.file ${escapeShellArg cfg.webConfigFile}"
] ++ optionals (cfg.configFile != null) [
"--config.file ${escapeShellArg cfg.configFile}"
] ++ extraFlags);
ExecStart =
with cfg;
concatStringsSep " " (
[
"${pkgs.prometheus-ipmi-exporter}/bin/ipmi_exporter"
"--web.listen-address ${listenAddress}:${toString port}"
]
++ optionals (cfg.webConfigFile != null) [
"--web.config.file ${escapeShellArg cfg.webConfigFile}"
]
++ optionals (cfg.configFile != null) [
"--config.file ${escapeShellArg cfg.configFile}"
]
++ extraFlags
);
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.jitsi;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.json;
@ -43,6 +49,9 @@ in
For more information, take a look at the official documentation
(https://github.com/prometheus-community/json_exporter) of the json_exporter.
'')
({ options.warnings = options.warnings; options.assertions = options.assertions; })
({
options.warnings = options.warnings;
options.assertions = options.assertions;
})
];
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.junos-czerwonk;
@ -10,9 +16,12 @@ let
concatStringsSep
;
configFile = if cfg.configuration != null then configurationFile else (escapeShellArg cfg.configurationFile);
configFile =
if cfg.configuration != null then configurationFile else (escapeShellArg cfg.configurationFile);
configurationFile = pkgs.writeText "prometheus-junos-czerwonk-exporter.conf" (builtins.toJSON (cfg.configuration));
configurationFile = pkgs.writeText "prometheus-junos-czerwonk-exporter.conf" (
builtins.toJSON (cfg.configuration)
);
in
{
port = 9326;

View file

@ -1,8 +1,9 @@
{ config
, lib
, pkgs
, utils
, ...
{
config,
lib,
pkgs,
utils,
...
}:
let
@ -13,7 +14,8 @@ let
mkRenamedOptionModule
literalExpression
;
in {
in
{
imports = [
(mkRenamedOptionModule [ "controlSocketPaths" ] [ "targets" ])
];
@ -41,11 +43,17 @@ in {
serviceConfig = {
User = "kea";
DynamicUser = true;
ExecStart = utils.escapeSystemdExecArgs ([
(lib.getExe pkgs.prometheus-kea-exporter)
"--address" cfg.listenAddress
"--port" cfg.port
] ++ cfg.extraFlags ++ cfg.targets);
ExecStart = utils.escapeSystemdExecArgs (
[
(lib.getExe pkgs.prometheus-kea-exporter)
"--address"
cfg.listenAddress
"--port"
cfg.port
]
++ cfg.extraFlags
++ cfg.targets
);
RuntimeDirectory = "kea";
RuntimeDirectoryPreserve = true;
RestrictAddressFamilies = [

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.keylight;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.knot;
@ -8,7 +14,8 @@ let
literalExpression
concatStringsSep
;
in {
in
{
port = 9433;
extraOpts = {
knotLibraryPath = mkOption {

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.lnd;
@ -40,6 +46,9 @@ in
${concatStringsSep " \\\n " cfg.extraFlags}
'';
LogsDirectory = "prometheus-lnd-exporter";
ReadOnlyPaths = [ cfg.lndTlsPath cfg.lndMacaroonDir ];
ReadOnlyPaths = [
cfg.lndTlsPath
cfg.lndMacaroonDir
];
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.mail;
@ -15,19 +21,29 @@ let
concatStringsSep
;
configFile = if cfg.configuration != null then configurationFile else (escapeShellArg cfg.configFile);
configFile =
if cfg.configuration != null then configurationFile else (escapeShellArg cfg.configFile);
configurationFile = pkgs.writeText "prometheus-mail-exporter.conf" (builtins.toJSON (
# removes the _module attribute, null values and converts attrNames to lowercase
mapAttrs' (name: value:
if name == "servers"
then nameValuePair (toLower name)
((map (srv: (mapAttrs' (n: v: nameValuePair (toLower n) v)
(filterAttrs (n: v: !(n == "_module" || v == null)) srv)
))) value)
else nameValuePair (toLower name) value
) (filterAttrs (n: _: !(n == "_module")) cfg.configuration)
));
configurationFile = pkgs.writeText "prometheus-mail-exporter.conf" (
builtins.toJSON (
# removes the _module attribute, null values and converts attrNames to lowercase
mapAttrs' (
name: value:
if name == "servers" then
nameValuePair (toLower name) (
(map (
srv:
(mapAttrs' (n: v: nameValuePair (toLower n) v) (
filterAttrs (n: v: !(n == "_module" || v == null)) srv
))
))
value
)
else
nameValuePair (toLower name) value
) (filterAttrs (n: _: !(n == "_module")) cfg.configuration)
)
);
serverOptions.options = {
name = mkOption {
@ -111,7 +127,7 @@ let
};
servers = mkOption {
type = types.listOf (types.submodule serverOptions);
default = [];
default = [ ];
example = literalExpression ''
[ {
name = "testserver";

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.mikrotik;
@ -53,19 +59,23 @@ in
'';
};
};
serviceOpts = let
configFile = if cfg.configFile != null
then cfg.configFile
else "${pkgs.writeText "mikrotik-exporter.yml" (builtins.toJSON cfg.configuration)}";
in {
serviceConfig = {
# -port is misleading name, it actually accepts address too
ExecStart = ''
${pkgs.prometheus-mikrotik-exporter}/bin/mikrotik-exporter \
-config-file=${escapeShellArg configFile} \
-port=${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
serviceOpts =
let
configFile =
if cfg.configFile != null then
cfg.configFile
else
"${pkgs.writeText "mikrotik-exporter.yml" (builtins.toJSON cfg.configuration)}";
in
{
serviceConfig = {
# -port is misleading name, it actually accepts address too
ExecStart = ''
${pkgs.prometheus-mikrotik-exporter}/bin/mikrotik-exporter \
-config-file=${escapeShellArg configFile} \
-port=${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.modemmanager;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.mongodb;
@ -25,7 +31,10 @@ in
collStats = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "db1.coll1" "db2" ];
example = [
"db1.coll1"
"db2"
];
description = ''
List of comma separared databases.collections to get $collStats
'';
@ -33,7 +42,10 @@ in
indexStats = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "db1.coll1" "db2" ];
example = [
"db1.coll1"
"db2"
];
description = ''
List of comma separared databases.collections to get $indexStats
'';
@ -41,7 +53,16 @@ in
collector = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "diagnosticdata" "replicasetstatus" "dbstats" "topmetrics" "currentopmetrics" "indexstats" "dbstats" "profile" ];
example = [
"diagnosticdata"
"replicasetstatus"
"dbstats"
"topmetrics"
"currentopmetrics"
"indexstats"
"dbstats"
"profile"
];
description = "Enabled collectors";
};
collectAll = mkOption {
@ -64,9 +85,22 @@ in
ExecStart = ''
${getExe pkgs.prometheus-mongodb-exporter} \
--mongodb.uri="${cfg.uri}" \
${if cfg.collectAll then "--collect-all" else concatMapStringsSep " " (x: "--collect.${x}") cfg.collector} \
${optionalString (length cfg.collStats > 0) "--mongodb.collstats-colls=${concatStringsSep "," cfg.collStats}"} \
${optionalString (length cfg.indexStats > 0) "--mongodb.indexstats-colls=${concatStringsSep "," cfg.indexStats}"} \
${
if cfg.collectAll then
"--collect-all"
else
concatMapStringsSep " " (x: "--collect.${x}") cfg.collector
} \
${
optionalString (
length cfg.collStats > 0
) "--mongodb.collstats-colls=${concatStringsSep "," cfg.collStats}"
} \
${
optionalString (
length cfg.indexStats > 0
) "--mongodb.indexstats-colls=${concatStringsSep "," cfg.indexStats}"
} \
--web.listen-address="${cfg.listenAddress}:${toString cfg.port}" \
--web.telemetry-path="${cfg.telemetryPath}" \
${escapeShellArgs cfg.extraFlags}

View file

@ -1,8 +1,24 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.mysqld;
inherit (lib) types mkOption mkIf mkForce cli concatStringsSep optionalString escapeShellArgs;
in {
inherit (lib)
types
mkOption
mkIf
mkForce
cli
concatStringsSep
optionalString
escapeShellArgs
;
in
{
port = 9104;
extraOpts = {
telemetryPath = mkOption {
@ -57,4 +73,3 @@ in {
};
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.nats;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.nextcloud;
@ -64,12 +70,17 @@ in
--addr ${cfg.listenAddress}:${toString cfg.port} \
--timeout ${cfg.timeout} \
--server ${cfg.url} \
${if cfg.passwordFile != null then ''
--username ${cfg.username} \
--password ${escapeShellArg "@${cfg.passwordFile}"} \
'' else ''
--auth-token ${escapeShellArg "@${cfg.tokenFile}"} \
''} \
${
if cfg.passwordFile != null then
''
--username ${cfg.username} \
--password ${escapeShellArg "@${cfg.passwordFile}"} \
''
else
''
--auth-token ${escapeShellArg "@${cfg.tokenFile}"} \
''
} \
${concatStringsSep " \\\n " cfg.extraFlags}'';
};
};

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.nginx;
@ -39,7 +45,7 @@ in
};
constLabels = mkOption {
type = types.listOf types.str;
default = [];
default = [ ];
example = [
"label1=value1"
"label2=value2"
@ -49,27 +55,37 @@ in
'';
};
};
serviceOpts = mkMerge ([{
environment.CONST_LABELS = concatStringsSep "," cfg.constLabels;
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-nginx-exporter}/bin/nginx-prometheus-exporter \
--nginx.scrape-uri='${cfg.scrapeUri}' \
--${lib.optionalString (!cfg.sslVerify) "no-"}nginx.ssl-verify \
--web.listen-address=${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path=${cfg.telemetryPath} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
}] ++ [(mkIf config.services.nginx.enable {
after = [ "nginx.service" ];
requires = [ "nginx.service" ];
})]);
serviceOpts = mkMerge (
[
{
environment.CONST_LABELS = concatStringsSep "," cfg.constLabels;
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-nginx-exporter}/bin/nginx-prometheus-exporter \
--nginx.scrape-uri='${cfg.scrapeUri}' \
--${lib.optionalString (!cfg.sslVerify) "no-"}nginx.ssl-verify \
--web.listen-address=${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path=${cfg.telemetryPath} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
}
]
++ [
(mkIf config.services.nginx.enable {
after = [ "nginx.service" ];
requires = [ "nginx.service" ];
})
]
);
imports = [
(mkRenamedOptionModule [ "telemetryEndpoint" ] [ "telemetryPath" ])
(mkRemovedOptionModule [ "insecure" ] ''
This option was replaced by 'prometheus.exporters.nginx.sslVerify'.
'')
({ options.warnings = options.warnings; options.assertions = options.assertions; })
({
options.warnings = options.warnings;
options.assertions = options.assertions;
})
];
}

View file

@ -1,9 +1,16 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.nginxlog;
inherit (lib) mkOption types;
in {
in
{
port = 9117;
extraOpts = {
settings = mkOption {
@ -19,7 +26,7 @@ in {
'';
};
namespaces = mkOption {
default = [];
default = [ ];
type = types.listOf (types.attrsOf types.anything);
description = ''
@ -28,7 +35,7 @@ in {
};
};
};
default = {};
default = { };
description = ''
All settings of nginxlog expressed as an Nix attrset.
@ -49,22 +56,26 @@ in {
};
};
serviceOpts = let
listenConfig = {
listen = {
port = cfg.port;
address = cfg.listenAddress;
metrics_endpoint = cfg.metricsEndpoint;
serviceOpts =
let
listenConfig = {
listen = {
port = cfg.port;
address = cfg.listenAddress;
metrics_endpoint = cfg.metricsEndpoint;
};
};
completeConfig = pkgs.writeText "nginxlog-exporter.yaml" (
builtins.toJSON (lib.recursiveUpdate listenConfig cfg.settings)
);
in
{
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-nginxlog-exporter}/bin/prometheus-nginxlog-exporter -config-file ${completeConfig}
'';
Restart = "always";
ProtectSystem = "full";
};
};
completeConfig = pkgs.writeText "nginxlog-exporter.yaml" (builtins.toJSON (lib.recursiveUpdate listenConfig cfg.settings));
in {
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-nginxlog-exporter}/bin/prometheus-nginxlog-exporter -config-file ${completeConfig}
'';
Restart="always";
ProtectSystem="full";
};
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.node;
@ -18,7 +24,7 @@ in
extraOpts = {
enabledCollectors = mkOption {
type = types.listOf types.str;
default = [];
default = [ ];
example = [ "systemd" ];
description = ''
Collectors to enable. The collectors listed here are enabled in addition to the default ones.
@ -26,7 +32,7 @@ in
};
disabledCollectors = mkOption {
type = types.listOf types.str;
default = [];
default = [ ];
example = [ "timex" ];
description = ''
Collectors to disable which are enabled by default.
@ -43,13 +49,17 @@ in
${concatMapStringsSep " " (x: "--no-collector." + x) cfg.disabledCollectors} \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} ${concatStringsSep " " cfg.extraFlags}
'';
RestrictAddressFamilies = optionals (collectorIsEnabled "logind" || collectorIsEnabled "systemd") [
# needs access to dbus via unix sockets (logind/systemd)
"AF_UNIX"
] ++ optionals (collectorIsEnabled "network_route" || collectorIsEnabled "wifi" || ! collectorIsDisabled "netdev") [
# needs netlink sockets for wireless collector
"AF_NETLINK"
];
RestrictAddressFamilies =
optionals (collectorIsEnabled "logind" || collectorIsEnabled "systemd") [
# needs access to dbus via unix sockets (logind/systemd)
"AF_UNIX"
]
++ optionals
(collectorIsEnabled "network_route" || collectorIsEnabled "wifi" || !collectorIsDisabled "netdev")
[
# needs netlink sockets for wireless collector
"AF_NETLINK"
];
# The timex collector needs to access clock APIs
ProtectClock = collectorIsDisabled "timex";
# Allow space monitoring under /home

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.nut;
@ -54,13 +60,18 @@ in
};
serviceOpts = {
script = ''
${optionalString (cfg.passwordPath != null)
"export NUT_EXPORTER_PASSWORD=$(cat ${toString cfg.passwordPath})"}
${optionalString (
cfg.passwordPath != null
) "export NUT_EXPORTER_PASSWORD=$(cat ${toString cfg.passwordPath})"}
${pkgs.prometheus-nut-exporter}/bin/nut_exporter \
--nut.server=${cfg.nutServer} \
--web.listen-address="${cfg.listenAddress}:${toString cfg.port}" \
${optionalString (cfg.nutUser != "") "--nut.username=${cfg.nutUser}"} \
${optionalString (cfg.nutVariables != []) "--nut.vars_enable=${concatStringsSep "," cfg.nutVariables}"} \
${
optionalString (
cfg.nutVariables != [ ]
) "--nut.vars_enable=${concatStringsSep "," cfg.nutVariables}"
} \
${concatStringsSep " " cfg.extraFlags}
'';
};

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.pgbouncer;
@ -90,7 +96,12 @@ in
};
logLevel = mkOption {
type = types.enum [ "debug" "info" "warn" "error" ];
type = types.enum [
"debug"
"info"
"warn"
"error"
];
default = "info";
description = ''
Only log messages with the given severity or above.
@ -98,7 +109,10 @@ in
};
logFormat = mkOption {
type = types.enum [ "logfmt" "json" ];
type = types.enum [
"logfmt"
"json"
];
default = "logfmt";
description = ''
Output format of log messages. One of: [logfmt, json]
@ -125,26 +139,40 @@ in
serviceOpts = {
after = [ "pgbouncer.service" ];
script = concatStringsSep " " ([
"exec -- ${escapeShellArg (getExe cfg.package)}"
"--web.listen-address ${cfg.listenAddress}:${toString cfg.port}"
] ++ optionals (cfg.connectionString != null) [
"--pgBouncer.connectionString ${escapeShellArg cfg.connectionString}"
] ++ optionals (cfg.telemetryPath != null) [
"--web.telemetry-path ${escapeShellArg cfg.telemetryPath}"
] ++ optionals (cfg.pidFile != null) [
"--pgBouncer.pid-file ${escapeShellArg cfg.pidFile}"
] ++ optionals (cfg.logLevel != null) [
"--log.level ${escapeShellArg cfg.logLevel}"
] ++ optionals (cfg.logFormat != null) [
"--log.format ${escapeShellArg cfg.logFormat}"
] ++ optionals (cfg.webSystemdSocket != false) [
"--web.systemd-socket ${escapeShellArg cfg.webSystemdSocket}"
] ++ optionals (cfg.webConfigFile != null) [
"--web.config.file ${escapeShellArg cfg.webConfigFile}"
] ++ cfg.extraFlags);
script = concatStringsSep " " (
[
"exec -- ${escapeShellArg (getExe cfg.package)}"
"--web.listen-address ${cfg.listenAddress}:${toString cfg.port}"
]
++ optionals (cfg.connectionString != null) [
"--pgBouncer.connectionString ${escapeShellArg cfg.connectionString}"
]
++ optionals (cfg.telemetryPath != null) [
"--web.telemetry-path ${escapeShellArg cfg.telemetryPath}"
]
++ optionals (cfg.pidFile != null) [
"--pgBouncer.pid-file ${escapeShellArg cfg.pidFile}"
]
++ optionals (cfg.logLevel != null) [
"--log.level ${escapeShellArg cfg.logLevel}"
]
++ optionals (cfg.logFormat != null) [
"--log.format ${escapeShellArg cfg.logFormat}"
]
++ optionals (cfg.webSystemdSocket != false) [
"--web.systemd-socket ${escapeShellArg cfg.webSystemdSocket}"
]
++ optionals (cfg.webConfigFile != null) [
"--web.config.file ${escapeShellArg cfg.webConfigFile}"
]
++ cfg.extraFlags
);
serviceConfig.RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
serviceConfig.RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
serviceConfig.EnvironmentFile = lib.mkIf (cfg.connectionEnvFile != null) [
cfg.connectionEnvFile
];
@ -160,6 +188,9 @@ in
into the cmdline of the exporter making the connection string effectively
world-readable.
'')
({ options.warnings = options.warnings; options.assertions = options.assertions; })
({
options.warnings = options.warnings;
options.assertions = options.assertions;
})
];
}

View file

@ -1,17 +1,19 @@
{ config
, lib
, pkgs
, options
, ...
{
config,
lib,
pkgs,
options,
...
}:
let
logPrefix = "services.prometheus.exporter.php-fpm";
cfg = config.services.prometheus.exporters.php-fpm;
in {
in
{
port = 9253;
extraOpts = {
package = lib.mkPackageOption pkgs "prometheus-php-fpm-exporter" {};
package = lib.mkPackageOption pkgs "prometheus-php-fpm-exporter" { };
telemetryPath = lib.mkOption {
type = lib.types.str;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.pihole;
@ -11,8 +17,11 @@ let
in
{
imports = [
(mkRemovedOptionModule [ "interval"] "This option has been removed.")
({ options.warnings = options.warnings; options.assertions = options.assertions; })
(mkRemovedOptionModule [ "interval" ] "This option has been removed.")
({
options.warnings = options.warnings;
options.assertions = options.assertions;
})
];
port = 9617;
@ -50,7 +59,10 @@ in
'';
};
protocol = mkOption {
type = types.enum [ "http" "https" ];
type = types.enum [
"http"
"https"
];
default = "http";
example = "https";
description = ''

View file

@ -1,11 +1,16 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.ping;
inherit (lib) mkOption types concatStringsSep;
settingsFormat = pkgs.formats.yaml {};
settingsFormat = pkgs.formats.yaml { };
configFile = settingsFormat.generate "config.yml" cfg.settings;
in
{
@ -21,7 +26,7 @@ in
settings = mkOption {
type = settingsFormat.type;
default = {};
default = { };
description = ''
Configuration for ping_exporter, see

View file

@ -98,22 +98,20 @@ in
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
--postfix.showq_path ${escapeShellArg cfg.showqPath} \
${
concatStringsSep " \\\n " (
cfg.extraFlags
++ optional cfg.systemd.enable "--systemd.enable"
++ optional cfg.systemd.enable (
if cfg.systemd.slice != null then
"--systemd.slice ${cfg.systemd.slice}"
else
"--systemd.unit ${cfg.systemd.unit}"
)
++ optional (
cfg.systemd.enable && (cfg.systemd.journalPath != null)
) "--systemd.journal_path ${escapeShellArg cfg.systemd.journalPath}"
++ optional (!cfg.systemd.enable) "--postfix.logfile_path ${escapeShellArg cfg.logfilePath}"
${concatStringsSep " \\\n " (
cfg.extraFlags
++ optional cfg.systemd.enable "--systemd.enable"
++ optional cfg.systemd.enable (
if cfg.systemd.slice != null then
"--systemd.slice ${cfg.systemd.slice}"
else
"--systemd.unit ${cfg.systemd.unit}"
)
}
++ optional (
cfg.systemd.enable && (cfg.systemd.journalPath != null)
) "--systemd.journal_path ${escapeShellArg cfg.systemd.journalPath}"
++ optional (!cfg.systemd.enable) "--postfix.logfile_path ${escapeShellArg cfg.logfilePath}"
)}
'';
};
};

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.postgres;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.process;
@ -15,7 +21,7 @@ in
extraOpts = {
settings.process_names = mkOption {
type = types.listOf types.anything;
default = [];
default = [ ];
example = literalExpression ''
[
# Remove nix store path from process name

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.pve;
@ -124,25 +130,27 @@ in
};
};
serviceOpts = {
serviceConfig = {
DynamicUser = cfg.environmentFile == null;
LoadCredential = "configFile:${computedConfigFile}";
ExecStart = ''
${cfg.package}/bin/pve_exporter \
--${optionalString (!cfg.collectors.status) "no-"}collector.status \
--${optionalString (!cfg.collectors.version) "no-"}collector.version \
--${optionalString (!cfg.collectors.node) "no-"}collector.node \
--${optionalString (!cfg.collectors.cluster) "no-"}collector.cluster \
--${optionalString (!cfg.collectors.resources) "no-"}collector.resources \
--${optionalString (!cfg.collectors.config) "no-"}collector.config \
--${optionalString (!cfg.collectors.replication) "no-"}collector.replication \
${optionalString (cfg.server.keyFile != null) "--server.keyfile ${cfg.server.keyFile}"} \
${optionalString (cfg.server.certFile != null) "--server.certfile ${cfg.server.certFile}"} \
--config.file %d/configFile \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port}
'';
} // optionalAttrs (cfg.environmentFile != null) {
EnvironmentFile = cfg.environmentFile;
};
serviceConfig =
{
DynamicUser = cfg.environmentFile == null;
LoadCredential = "configFile:${computedConfigFile}";
ExecStart = ''
${cfg.package}/bin/pve_exporter \
--${optionalString (!cfg.collectors.status) "no-"}collector.status \
--${optionalString (!cfg.collectors.version) "no-"}collector.version \
--${optionalString (!cfg.collectors.node) "no-"}collector.node \
--${optionalString (!cfg.collectors.cluster) "no-"}collector.cluster \
--${optionalString (!cfg.collectors.resources) "no-"}collector.resources \
--${optionalString (!cfg.collectors.config) "no-"}collector.config \
--${optionalString (!cfg.collectors.replication) "no-"}collector.replication \
${optionalString (cfg.server.keyFile != null) "--server.keyfile ${cfg.server.keyFile}"} \
${optionalString (cfg.server.certFile != null) "--server.certfile ${cfg.server.certFile}"} \
--config.file %d/configFile \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port}
'';
}
// optionalAttrs (cfg.environmentFile != null) {
EnvironmentFile = cfg.environmentFile;
};
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.py-air-control;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.redis;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.restic;
@ -62,7 +68,12 @@ in
};
rcloneOptions = mkOption {
type = with types; attrsOf (oneOf [ str bool ]);
type =
with types;
attrsOf (oneOf [
str
bool
]);
default = { };
description = ''
Options to pass to rclone to control its behavior.
@ -75,7 +86,12 @@ in
};
rcloneConfig = mkOption {
type = with types; attrsOf (oneOf [ str bool ]);
type =
with types;
attrsOf (oneOf [
str
bool
]);
default = { };
description = ''
Configuration for the rclone remote being used for backup.
@ -114,9 +130,10 @@ in
serviceOpts = {
script = ''
export RESTIC_REPOSITORY=${
if cfg.repositoryFile != null
then "$(cat $CREDENTIALS_DIRECTORY/RESTIC_REPOSITORY)"
else "${cfg.repository}"
if cfg.repositoryFile != null then
"$(cat $CREDENTIALS_DIRECTORY/RESTIC_REPOSITORY)"
else
"${cfg.repository}"
}
export RESTIC_PASSWORD_FILE=$CREDENTIALS_DIRECTORY/RESTIC_PASSWORD_FILE
${pkgs.prometheus-restic-exporter}/bin/restic-exporter.py \
@ -124,10 +141,9 @@ in
'';
serviceConfig = {
EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile;
LoadCredential =
[ "RESTIC_PASSWORD_FILE:${cfg.passwordFile}" ]
++ optional (cfg.repositoryFile != null)
[ "RESTIC_REPOSITORY:${cfg.repositoryFile}" ];
LoadCredential = [
"RESTIC_PASSWORD_FILE:${cfg.passwordFile}"
] ++ optional (cfg.repositoryFile != null) [ "RESTIC_REPOSITORY:${cfg.repositoryFile}" ];
};
environment =
let
@ -141,18 +157,14 @@ in
LISTEN_PORT = toString cfg.port;
REFRESH_INTERVAL = toString cfg.refreshInterval;
}
// (mapAttrs'
(name: value:
nameValuePair (rcloneAttrToOpt name) (toRcloneVal value)
)
cfg.rcloneOptions)
// (mapAttrs' (
name: value: nameValuePair (rcloneAttrToOpt name) (toRcloneVal value)
) cfg.rcloneOptions)
// optionalAttrs (cfg.rcloneConfigFile != null) {
RCLONE_CONFIG = cfg.rcloneConfigFile;
}
// (mapAttrs'
(name: value:
nameValuePair (rcloneAttrToConf name) (toRcloneVal value)
)
cfg.rcloneConfig);
// (mapAttrs' (
name: value: nameValuePair (rcloneAttrToConf name) (toRcloneVal value)
) cfg.rcloneConfig);
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.rspamd;
@ -12,53 +18,59 @@ let
literalExpression
;
mkFile = conf:
pkgs.writeText "rspamd-exporter-config.yml" (builtins.toJSON conf);
mkFile = conf: pkgs.writeText "rspamd-exporter-config.yml" (builtins.toJSON conf);
generateConfig = extraLabels: {
modules.default.metrics = (map (path: {
name = "rspamd_${replaceStrings [ "[" "." " " "]" "\\" "'" ] [ "_" "_" "_" "" "" "" ] path}";
path = "{ .${path} }";
labels = extraLabels;
}) [
"actions['add\\ header']"
"actions['no\\ action']"
"actions['rewrite\\ subject']"
"actions['soft\\ reject']"
"actions.greylist"
"actions.reject"
"bytes_allocated"
"chunks_allocated"
"chunks_freed"
"chunks_oversized"
"connections"
"control_connections"
"ham_count"
"learned"
"pools_allocated"
"pools_freed"
"read_only"
"scanned"
"shared_chunks_allocated"
"spam_count"
"total_learns"
]) ++ [{
name = "rspamd_statfiles";
type = "object";
path = "{.statfiles[*]}";
labels = recursiveUpdate {
symbol = "{.symbol}";
type = "{.type}";
} extraLabels;
values = {
revision = "{.revision}";
size = "{.size}";
total = "{.total}";
used = "{.used}";
languages = "{.languages}";
users = "{.users}";
};
}];
modules.default.metrics =
(map
(path: {
name = "rspamd_${replaceStrings [ "[" "." " " "]" "\\" "'" ] [ "_" "_" "_" "" "" "" ] path}";
path = "{ .${path} }";
labels = extraLabels;
})
[
"actions['add\\ header']"
"actions['no\\ action']"
"actions['rewrite\\ subject']"
"actions['soft\\ reject']"
"actions.greylist"
"actions.reject"
"bytes_allocated"
"chunks_allocated"
"chunks_freed"
"chunks_oversized"
"connections"
"control_connections"
"ham_count"
"learned"
"pools_allocated"
"pools_freed"
"read_only"
"scanned"
"shared_chunks_allocated"
"spam_count"
"total_learns"
]
)
++ [
{
name = "rspamd_statfiles";
type = "object";
path = "{.statfiles[*]}";
labels = recursiveUpdate {
symbol = "{.symbol}";
type = "{.type}";
} extraLabels;
values = {
revision = "{.revision}";
size = "{.size}";
total = "{.total}";
used = "{.used}";
languages = "{.languages}";
users = "{.users}";
};
}
];
};
in
{
@ -99,6 +111,9 @@ in
For more information, take a look at the official documentation
(https://github.com/prometheus-community/json_exporter) of the json_exporter.
'')
({ options.warnings = options.warnings; options.assertions = options.assertions; })
({
options.warnings = options.warnings;
options.assertions = options.assertions;
})
];
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.rtl_433;
@ -6,56 +12,67 @@ in
{
port = 9550;
extraOpts = let
mkMatcherOptionType = field: description: with lib.types;
listOf (submodule {
options = {
name = lib.mkOption {
type = str;
description = "Name to match.";
extraOpts =
let
mkMatcherOptionType =
field: description:
with lib.types;
listOf (submodule {
options = {
name = lib.mkOption {
type = str;
description = "Name to match.";
};
"${field}" = lib.mkOption {
type = int;
description = description;
};
location = lib.mkOption {
type = str;
description = "Location to match.";
};
};
"${field}" = lib.mkOption {
type = int;
description = description;
};
location = lib.mkOption {
type = str;
description = "Location to match.";
};
};
});
in
{
rtl433Flags = lib.mkOption {
type = lib.types.str;
default = "-C si";
example = "-C si -R 19";
description = ''
Flags passed verbatim to rtl_433 binary.
Having `-C si` (the default) is recommended since only Celsius temperatures are parsed.
'';
});
in
{
rtl433Flags = lib.mkOption {
type = lib.types.str;
default = "-C si";
example = "-C si -R 19";
description = ''
Flags passed verbatim to rtl_433 binary.
Having `-C si` (the default) is recommended since only Celsius temperatures are parsed.
'';
};
channels = lib.mkOption {
type = mkMatcherOptionType "channel" "Channel to match.";
default = [ ];
example = [
{
name = "Acurite";
channel = 6543;
location = "Kitchen";
}
];
description = ''
List of channel matchers to export.
'';
};
ids = lib.mkOption {
type = mkMatcherOptionType "id" "ID to match.";
default = [ ];
example = [
{
name = "Nexus";
id = 1;
location = "Bedroom";
}
];
description = ''
List of ID matchers to export.
'';
};
};
channels = lib.mkOption {
type = mkMatcherOptionType "channel" "Channel to match.";
default = [];
example = [
{ name = "Acurite"; channel = 6543; location = "Kitchen"; }
];
description = ''
List of channel matchers to export.
'';
};
ids = lib.mkOption {
type = mkMatcherOptionType "id" "ID to match.";
default = [];
example = [
{ name = "Nexus"; id = 1; location = "Bedroom"; }
];
description = ''
List of ID matchers to export.
'';
};
};
serviceOpts = {
serviceConfig = {
@ -66,18 +83,19 @@ in
DeviceAllow = lib.mkForce "char-usb_device rw";
RestrictAddressFamilies = [ "AF_NETLINK" ];
ExecStart = let
matchers = (map (m:
"--channel_matcher '${m.name},${toString m.channel},${m.location}'"
) cfg.channels) ++ (map (m:
"--id_matcher '${m.name},${toString m.id},${m.location}'"
) cfg.ids); in ''
${pkgs.prometheus-rtl_433-exporter}/bin/rtl_433_prometheus \
-listen ${cfg.listenAddress}:${toString cfg.port} \
-subprocess "${pkgs.rtl_433}/bin/rtl_433 -F json ${cfg.rtl433Flags}" \
${lib.concatStringsSep " \\\n " matchers} \
${lib.concatStringsSep " \\\n " cfg.extraFlags}
'';
ExecStart =
let
matchers =
(map (m: "--channel_matcher '${m.name},${toString m.channel},${m.location}'") cfg.channels)
++ (map (m: "--id_matcher '${m.name},${toString m.id},${m.location}'") cfg.ids);
in
''
${pkgs.prometheus-rtl_433-exporter}/bin/rtl_433_prometheus \
-listen ${cfg.listenAddress}:${toString cfg.port} \
-subprocess "${pkgs.rtl_433}/bin/rtl_433 -F json ${cfg.rtl433Flags}" \
${lib.concatStringsSep " \\\n " matchers} \
${lib.concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
inherit (lib) mkOption types;
@ -10,31 +16,36 @@ in
extraOpts = {
servers = mkOption {
description = "List of sabnzbd servers to connect to.";
type = types.listOf (types.submodule {
options = {
baseUrl = mkOption {
type = types.str;
description = "Base URL of the sabnzbd server.";
example = "http://localhost:8080/sabnzbd";
type = types.listOf (
types.submodule {
options = {
baseUrl = mkOption {
type = types.str;
description = "Base URL of the sabnzbd server.";
example = "http://localhost:8080/sabnzbd";
};
apiKeyFile = mkOption {
type = types.str;
description = ''
The path to a file containing the API key.
The file is securely passed to the service by leveraging systemd credentials.
No special permissions need to be set on this file.
'';
example = "/run/secrets/sabnzbd_apikey";
};
};
apiKeyFile = mkOption {
type = types.str;
description = ''
The path to a file containing the API key.
The file is securely passed to the service by leveraging systemd credentials.
No special permissions need to be set on this file.
'';
example = "/run/secrets/sabnzbd_apikey";
};
};
});
}
);
};
};
serviceOpts =
let
servers = lib.zipAttrs cfg.servers;
credentials = lib.imap0 (i: v: { name = "apikey-${toString i}"; path = v; }) servers.apiKeyFile;
credentials = lib.imap0 (i: v: {
name = "apikey-${toString i}";
path = v;
}) servers.apiKeyFile;
in
{
serviceConfig.LoadCredential = builtins.map ({ name, path }: "${name}:${path}") credentials;
@ -47,7 +58,9 @@ in
script =
let
apiKeys = lib.concatStringsSep "," (builtins.map (cred: "$(< $CREDENTIALS_DIRECTORY/${cred.name})") credentials);
apiKeys = lib.concatStringsSep "," (
builtins.map (cred: "$(< $CREDENTIALS_DIRECTORY/${cred.name})") credentials
);
in
''
export SABNZBD_APIKEYS="${apiKeys}"

View file

@ -1,14 +1,16 @@
{ config
, lib
, pkgs
, options
, ...
{
config,
lib,
pkgs,
options,
...
}:
let
logPrefix = "services.prometheus.exporter.scaphandre";
cfg = config.services.prometheus.exporters.scaphandre;
in {
in
{
port = 8080;
extraOpts = {
telemetryPath = lib.mkOption {

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.script;
@ -14,26 +20,28 @@ in
port = 9172;
extraOpts = {
settings.scripts = mkOption {
type = with types; listOf (submodule {
options = {
name = mkOption {
type = str;
example = "sleep";
description = "Name of the script.";
type =
with types;
listOf (submodule {
options = {
name = mkOption {
type = str;
example = "sleep";
description = "Name of the script.";
};
script = mkOption {
type = str;
example = "sleep 5";
description = "Shell script to execute when metrics are requested.";
};
timeout = mkOption {
type = nullOr int;
default = null;
example = 60;
description = "Optional timeout for the script in seconds.";
};
};
script = mkOption {
type = str;
example = "sleep 5";
description = "Shell script to execute when metrics are requested.";
};
timeout = mkOption {
type = nullOr int;
default = null;
example = 60;
description = "Optional timeout for the script in seconds.";
};
};
});
});
example = literalExpression ''
{
scripts = [

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.shelly;

View file

@ -1,15 +1,24 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.smartctl;
inherit (lib) mkOption types literalExpression;
args = lib.escapeShellArgs ([
"--web.listen-address=${cfg.listenAddress}:${toString cfg.port}"
"--smartctl.interval=${cfg.maxInterval}"
] ++ map (device: "--smartctl.device=${device}") cfg.devices
++ cfg.extraFlags);
args = lib.escapeShellArgs (
[
"--web.listen-address=${cfg.listenAddress}:${toString cfg.port}"
"--smartctl.interval=${cfg.maxInterval}"
]
++ map (device: "--smartctl.device=${device}") cfg.devices
++ cfg.extraFlags
);
in
{
@ -58,8 +67,14 @@ in
PrivateDevices = lib.mkForce false;
ProtectProc = "invisible";
ProcSubset = "pid";
SupplementaryGroups = [ "disk" "smartctl-exporter-access" ];
SystemCallFilter = [ "@system-service" "~@privileged" ];
SupplementaryGroups = [
"disk"
"smartctl-exporter-access"
];
SystemCallFilter = [
"@system-service"
"~@privileged"
];
};
};
}

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.smokeping;
@ -6,7 +12,8 @@ let
goDuration = types.mkOptionType {
name = "goDuration";
description = "Go duration (https://golang.org/pkg/time/#ParseDuration)";
check = x: types.str.check x && builtins.match "(-?[0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+" x != null;
check =
x: types.str.check x && builtins.match "(-?[0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+" x != null;
inherit (types.str) merge;
};
in

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.sql;
inherit (lib)
@ -32,7 +38,7 @@ let
};
startupSql = mkOption {
type = listOf str;
default = [];
default = [ ];
description = "A list of SQL statements to execute once after making a connection.";
};
queries = mkOption {
@ -65,15 +71,16 @@ let
};
configFile =
if cfg.configFile != null
then cfg.configFile
if cfg.configFile != null then
cfg.configFile
else
let
nameInline = mapAttrsToList (k: v: v // { name = k; });
renameStartupSql = j: removeAttrs (j // { startup_sql = j.startupSql; }) [ "startupSql" ];
configuration = {
jobs = map renameStartupSql
(nameInline (mapAttrs (k: v: (v // { queries = nameInline v.queries; })) cfg.configuration.jobs));
jobs = map renameStartupSql (
nameInline (mapAttrs (k: v: (v // { queries = nameInline v.queries; })) cfg.configuration.jobs)
);
};
in
builtins.toFile "config.yaml" (builtins.toJSON configuration);

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.statsd;

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.surfboard;

View file

@ -1,9 +1,15 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.prometheus.exporters.systemd;
inherit (lib) concatStringsSep;
in {
in
{
port = 9558;
serviceOpts = {

View file

@ -1,8 +1,9 @@
{ config
, lib
, pkgs
, options
, ...
{
config,
lib,
pkgs,
options,
...
}:
let
@ -19,9 +20,16 @@ let
in
{
imports = [
(mkRemovedOptionModule [ "controlInterface" ] "This option was removed, use the `unbound.host` option instead.")
(mkRemovedOptionModule [ "fetchType" ] "This option was removed, use the `unbound.host` option instead.")
({ options.warnings = options.warnings; options.assertions = options.assertions; })
(mkRemovedOptionModule [
"controlInterface"
] "This option was removed, use the `unbound.host` option instead.")
(mkRemovedOptionModule [
"fetchType"
] "This option was removed, use the `unbound.host` option instead.")
({
options.warnings = options.warnings;
options.assertions = options.assertions;
})
];
port = 9167;
@ -73,31 +81,38 @@ in
};
};
serviceOpts = mkMerge ([{
serviceConfig = {
User = "unbound"; # to access the unbound_control.key
ExecStart = ''
${pkgs.prometheus-unbound-exporter}/bin/unbound_exporter \
--unbound.host "${cfg.unbound.host}" \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
${optionalString (cfg.unbound.ca != null) "--unbound.ca ${cfg.unbound.ca}"} \
${optionalString (cfg.unbound.certificate != null) "--unbound.cert ${cfg.unbound.certificate}"} \
${optionalString (cfg.unbound.key != null) "--unbound.key ${cfg.unbound.key}"} \
${toString cfg.extraFlags}
'';
RestrictAddressFamilies = [
"AF_UNIX"
"AF_INET"
"AF_INET6"
];
} // optionalAttrs (!config.services.unbound.enable) {
DynamicUser = true;
};
}] ++ [
(mkIf config.services.unbound.enable {
after = [ "unbound.service" ];
requires = [ "unbound.service" ];
})
]);
serviceOpts = mkMerge (
[
{
serviceConfig =
{
User = "unbound"; # to access the unbound_control.key
ExecStart = ''
${pkgs.prometheus-unbound-exporter}/bin/unbound_exporter \
--unbound.host "${cfg.unbound.host}" \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
${optionalString (cfg.unbound.ca != null) "--unbound.ca ${cfg.unbound.ca}"} \
${optionalString (cfg.unbound.certificate != null) "--unbound.cert ${cfg.unbound.certificate}"} \
${optionalString (cfg.unbound.key != null) "--unbound.key ${cfg.unbound.key}"} \
${toString cfg.extraFlags}
'';
RestrictAddressFamilies = [
"AF_UNIX"
"AF_INET"
"AF_INET6"
];
}
// optionalAttrs (!config.services.unbound.enable) {
DynamicUser = true;
};
}
]
++ [
(mkIf config.services.unbound.enable {
after = [ "unbound.service" ];
requires = [ "unbound.service" ];
})
]
);
}

View file

@ -1,22 +1,31 @@
{ config, lib, pkgs, options, ... }:
{
config,
lib,
pkgs,
options,
...
}:
let
cfg = config.services.prometheus.exporters.unpoller;
inherit (lib) mkEnableOption generators;
configFile = pkgs.writeText "prometheus-unpoller-exporter.json" (generators.toJSON {} {
poller = { inherit (cfg.log) debug quiet; };
unifi = { inherit (cfg) controllers; };
influxdb.disable = true;
datadog.disable = true; # workaround for https://github.com/unpoller/unpoller/issues/442
prometheus = {
http_listen = "${cfg.listenAddress}:${toString cfg.port}";
report_errors = cfg.log.prometheusErrors;
};
inherit (cfg) loki;
});
configFile = pkgs.writeText "prometheus-unpoller-exporter.json" (
generators.toJSON { } {
poller = { inherit (cfg.log) debug quiet; };
unifi = { inherit (cfg) controllers; };
influxdb.disable = true;
datadog.disable = true; # workaround for https://github.com/unpoller/unpoller/issues/442
prometheus = {
http_listen = "${cfg.listenAddress}:${toString cfg.port}";
report_errors = cfg.log.prometheusErrors;
};
inherit (cfg) loki;
}
);
in {
in
{
port = 9130;
extraOpts = {

Some files were not shown because too many files have changed in this diff Show more