diff options
author | github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> | 2024-02-02 00:02:44 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-02 00:02:44 +0000 |
commit | 6b866c8f85eecb03db15a072fef56711f934bc27 (patch) | |
tree | cbb52d6c6176cb9ca5a55e2ba6ef5b5d400b2f13 /nixos | |
parent | d4b73625ba28c3f58be305eb89734c1181c3931e (diff) | |
parent | 1bfd22b6448ac4d407510bd37fe16d87a9dcb41b (diff) | |
download | nixlib-6b866c8f85eecb03db15a072fef56711f934bc27.tar nixlib-6b866c8f85eecb03db15a072fef56711f934bc27.tar.gz nixlib-6b866c8f85eecb03db15a072fef56711f934bc27.tar.bz2 nixlib-6b866c8f85eecb03db15a072fef56711f934bc27.tar.lz nixlib-6b866c8f85eecb03db15a072fef56711f934bc27.tar.xz nixlib-6b866c8f85eecb03db15a072fef56711f934bc27.tar.zst nixlib-6b866c8f85eecb03db15a072fef56711f934bc27.zip |
Merge staging-next into staging
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/modules/security/wrappers/wrapper.c | 7 | ||||
-rw-r--r-- | nixos/modules/services/monitoring/prometheus/exporters.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/monitoring/prometheus/exporters/restic.nix | 131 | ||||
-rw-r--r-- | nixos/tests/prometheus-exporters.nix | 40 |
4 files changed, 178 insertions, 1 deletions
diff --git a/nixos/modules/security/wrappers/wrapper.c b/nixos/modules/security/wrappers/wrapper.c index 3277e7ef6f79..3e126875c687 100644 --- a/nixos/modules/security/wrappers/wrapper.c +++ b/nixos/modules/security/wrappers/wrapper.c @@ -172,6 +172,13 @@ static int make_caps_ambient(const char *self_path) { int main(int argc, char **argv) { ASSERT(argc >= 1); + // argv[0] goes into a lot of places, to a far greater degree than other elements + // of argv. glibc has had buffer overflows relating to argv[0], eg CVE-2023-6246. + // Since we expect the wrappers to be invoked from either $PATH or /run/wrappers/bin, + // there should be no reason to pass any particularly large values here, so we can + // be strict for strictness' sake. + ASSERT(strlen(argv[0]) < 512); + int debug = getenv(wrapper_debug) != NULL; // Drop insecure environment variables explicitly diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix index 0583b12fe7a3..6be6ba7edf72 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters.nix @@ -70,6 +70,7 @@ let "pve" "py-air-control" "redis" + "restic" "rspamd" "rtl_433" "sabnzbd" diff --git a/nixos/modules/services/monitoring/prometheus/exporters/restic.nix b/nixos/modules/services/monitoring/prometheus/exporters/restic.nix new file mode 100644 index 000000000000..5b32c93a666d --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/exporters/restic.nix @@ -0,0 +1,131 @@ +{ config, lib, pkgs, options }: + +with lib; + +let + cfg = config.services.prometheus.exporters.restic; +in +{ + port = 9753; + extraOpts = { + repository = mkOption { + type = types.str; + description = lib.mdDoc '' + URI pointing to the repository to monitor. + ''; + example = "sftp:backup@192.168.1.100:/backups/example"; + }; + + passwordFile = mkOption { + type = types.path; + description = lib.mdDoc '' + File containing the password to the repository. + ''; + example = "/etc/nixos/restic-password"; + }; + + environmentFile = mkOption { + type = with types; nullOr path; + default = null; + description = lib.mdDoc '' + File containing the credentials to access the repository, in the + format of an EnvironmentFile as described by systemd.exec(5) + ''; + }; + + refreshInterval = mkOption { + type = types.ints.unsigned; + default = 60; + description = lib.mdDoc '' + Refresh interval for the metrics in seconds. + Computing the metrics is an expensive task, keep this value as high as possible. + ''; + }; + + rcloneOptions = mkOption { + type = with types; attrsOf (oneOf [ str bool ]); + default = { }; + description = lib.mdDoc '' + Options to pass to rclone to control its behavior. + See <https://rclone.org/docs/#options> for + available options. When specifying option names, strip the + leading `--`. To set a flag such as + `--drive-use-trash`, which does not take a value, + set the value to the Boolean `true`. + ''; + }; + + rcloneConfig = mkOption { + type = with types; attrsOf (oneOf [ str bool ]); + default = { }; + description = lib.mdDoc '' + Configuration for the rclone remote being used for backup. + See the remote's specific options under rclone's docs at + <https://rclone.org/docs/>. When specifying + option names, use the "config" name specified in the docs. + For example, to set `--b2-hard-delete` for a B2 + remote, use `hard_delete = true` in the + attribute set. + + ::: {.warning} + Secrets set in here will be world-readable in the Nix + store! Consider using the {option}`rcloneConfigFile` + option instead to specify secret values separately. Note that + options set here will override those set in the config file. + ::: + ''; + }; + + rcloneConfigFile = mkOption { + type = with types; nullOr path; + default = null; + description = lib.mdDoc '' + Path to the file containing rclone configuration. This file + must contain configuration for the remote specified in this backup + set and also must be readable by root. + + ::: {.caution} + Options set in `rcloneConfig` will override those set in this + file. + ::: + ''; + }; + }; + + serviceOpts = { + serviceConfig = { + ExecStart = '' + ${pkgs.prometheus-restic-exporter}/bin/restic-exporter.py \ + ${concatStringsSep " \\\n " cfg.extraFlags} + ''; + EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile; + }; + environment = + let + rcloneRemoteName = builtins.elemAt (splitString ":" cfg.repository) 1; + rcloneAttrToOpt = v: "RCLONE_" + toUpper (builtins.replaceStrings [ "-" ] [ "_" ] v); + rcloneAttrToConf = v: "RCLONE_CONFIG_" + toUpper (rcloneRemoteName + "_" + v); + toRcloneVal = v: if lib.isBool v then lib.boolToString v else v; + in + { + RESTIC_REPO_URL = cfg.repository; + RESTIC_REPO_PASSWORD_FILE = cfg.passwordFile; + LISTEN_ADDRESS = cfg.listenAddress; + LISTEN_PORT = toString cfg.port; + REFRESH_INTERVAL = toString cfg.refreshInterval; + } + // (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); + }; +} diff --git a/nixos/tests/prometheus-exporters.nix b/nixos/tests/prometheus-exporters.nix index 0f8e355b2f4c..7e74f27174ec 100644 --- a/nixos/tests/prometheus-exporters.nix +++ b/nixos/tests/prometheus-exporters.nix @@ -1177,6 +1177,39 @@ let ''; }; + restic = + let + repository = "rest:http://127.0.0.1:8000"; + passwordFile = pkgs.writeText "restic-test-password" "test-password"; + in + { + exporterConfig = { + enable = true; + inherit repository passwordFile; + }; + metricProvider = { + services.restic.server = { + enable = true; + extraFlags = [ "--no-auth" ]; + }; + environment.systemPackages = [ pkgs.restic ]; + }; + exporterTest = '' + # prometheus-restic-exporter.service fails without initialised repository + systemctl("stop prometheus-restic-exporter.service") + + # Initialise the repository + wait_for_unit("restic-rest-server.service") + wait_for_open_port(8000) + succeed("restic init --repo ${repository} --password-file ${passwordFile}") + + systemctl("start prometheus-restic-exporter.service") + wait_for_unit("prometheus-restic-exporter.service") + wait_for_open_port(9753) + wait_until_succeeds("curl -sSf localhost:9753/metrics | grep 'restic_check_success 1.0'") + ''; + }; + rspamd = { exporterConfig = { enable = true; @@ -1684,7 +1717,12 @@ mapAttrs testScript = '' ${nodeName}.start() ${concatStringsSep "\n" (map (line: - if (builtins.substring 0 1 line == " " || builtins.substring 0 1 line == ")") + if builtins.any (b: b) [ + (builtins.match "^[[:space:]]*$" line != null) + (builtins.substring 0 1 line == "#") + (builtins.substring 0 1 line == " ") + (builtins.substring 0 1 line == ")") + ] then line else "${nodeName}.${line}" ) (splitString "\n" (removeSuffix "\n" testConfig.exporterTest)))} |