Unverified Commit 302c564b authored by nixpkgs-ci[bot]'s avatar nixpkgs-ci[bot] Committed by GitHub
Browse files

Merge master into staging-next

parents a52caafe 39a15b69
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -475,6 +475,8 @@ and [release notes for v18](https://goteleport.com/docs/changelog/#1800-070325).

- `services.restic.backups` now includes a `command` option for passing a command to the [--stdin-from-command](https://github.com/restic/restic/pull/4410) flag.

- `services.grafana` does no longer send usage statistics by default.

- `services.postsrsd` now automatically integrates with the local Postfix instance, when enabled. This behavior can disabled using the [services.postsrsd.configurePostfix](#opt-services.postsrsd.configurePostfix) option.

- `services.pfix-srsd` now automatically integrates with the local Postfix instance, when enabled. This behavior can disabled using the [services.pfix-srsd.configurePostfix](#opt-services.pfix-srsd.configurePostfix) option.
+23 −1
Original line number Diff line number Diff line
@@ -16,6 +16,18 @@ let
    ;

  cfg = config.networking.stevenblack;

  filterHostsFile =
    hostsFile:
    if cfg.whitelist == [ ] then
      hostsFile
    else
      let
        pattern = lib.escape [ "." "|" ] (lib.concatStringsSep "|" cfg.whitelist);
      in
      pkgs.runCommand "filtered-hosts" { } ''
        sed '/${pattern}/d' ${hostsFile} > $out
      '';
in
{
  options.networking.stevenblack = {
@@ -35,10 +47,20 @@ in
      default = [ ];
      description = "Additional blocklist extensions.";
    };

    whitelist = mkOption {
      # https://datatracker.ietf.org/doc/html/rfc1035
      type = types.listOf (types.strMatching "^[a-zA-Z0-9_-]+([.][a-zA-Z0-9_-]+)+$");
      default = [ ];
      description = "Domains to exclude from blocking.";
      example = [ "s.click.aliexpress.com" ];
    };
  };

  config = mkIf cfg.enable {
    networking.hostFiles = map (x: "${getOutput x cfg.package}/hosts") ([ "ads" ] ++ cfg.block);
    networking.hostFiles = map (x: filterHostsFile "${getOutput x cfg.package}/hosts") (
      [ "ads" ] ++ cfg.block
    );
  };

  meta.maintainers = with maintainers; [
+1 −38
Original line number Diff line number Diff line
@@ -289,6 +289,7 @@

      systemd.services.nvidia-container-toolkit-cdi-generator = {
        description = "Container Device Interface (CDI) for Nvidia generator";
        after = [ "systemd-udev-settle.service" ];
        requiredBy = lib.mkMerge [
          (lib.mkIf config.virtualisation.docker.enable [ "docker.service" ])
          (lib.mkIf config.virtualisation.podman.enable [ "podman.service" ])
@@ -297,44 +298,6 @@
        serviceConfig = {
          RuntimeDirectory = "cdi";
          RemainAfterExit = true;
          ExecStartPre = pkgs.writeShellScript "wait-for-nvidia-devices" ''
            set -eu

            gpus_dir="/proc/driver/nvidia/gpus"
            max_wait_seconds=60

            if [ ! -d "$gpus_dir" ]; then
              echo "wait-for-nvidia-devices: $gpus_dir does not exist; nothing to wait for."
              exit 0
            fi

            gpu_count=$(find "$gpus_dir" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l | tr -d ' ')

            if [ "$gpu_count" -eq 0 ]; then
              echo "wait-for-nvidia-devices: no GPU entries found in $gpus_dir; nothing to wait for."
              exit 0
            fi

            echo "wait-for-nvidia-devices: expecting $gpu_count /dev/nvidiaN device node(s)."

            elapsed=0
            while true; do
              dev_count=$(find /dev -mindepth 1 -maxdepth 1 -type c -regex '.*/nvidia[0-9]+' 2>/dev/null | wc -l | tr -d ' ')

              if [ "$dev_count" -eq "$gpu_count" ]; then
                echo "wait-for-nvidia-devices: found $dev_count matching device node(s)."
                exit 0
              fi

              if [ "$elapsed" -ge "$max_wait_seconds" ]; then
                echo "wait-for-nvidia-devices: timed out after $max_wait_seconds seconds; expected $gpu_count node(s) but found $dev_count." >&2
                exit 1
              fi

              sleep 1
              elapsed=$((elapsed + 1))
            done
          '';
          ExecStart =
            let
              script = pkgs.callPackage ./cdi-generate.nix {
+187 −95
Original line number Diff line number Diff line
@@ -2,108 +2,186 @@
  lib,
  pkgs,
  config,
  utils,
  ...
}:
let
  cfg = config.services.grafana-image-renderer;

  format = pkgs.formats.json { };

  configFile = format.generate "grafana-image-renderer-config.json" cfg.settings;
  format = {
    type =
      with lib.types;
      attrsOf (
        attrsOf (oneOf [
          str
          int
          bool
          (listOf (oneOf [
            str
            int
          ]))
        ])
      );

    generate = lib.flip lib.pipe [
      # Remove legacy option prefixes that only exist for backwards-compat
      (lib.flip builtins.removeAttrs [
        "service"
        "rendering"
        "assertions"
        "warnings"
      ])

      # Normalize CLI args from a nested attr-set to `section.option = value`
      (lib.concatMapAttrs (block: lib.mapAttrs' (option: lib.nameValuePair "${block}.${option}")))

      # Turn attr-set into a list of arguments, denormalize list options.
      (lib.mapAttrsToList (
        option: value:
        if lib.isBool value then
          lib.optional value "--${option}"
        else if lib.isList value then
          map (v: [
            "--${option}"
            v
          ]) value
        else
          [
            "--${option}"
            (toString value)
          ]
      ))
      lib.flatten

      # Turn into a string
      utils.escapeSystemdExecArgs
    ];
  };
in
{
  imports = [
    (lib.mkChangedOptionModule
      [
        "services"
        "grafana-image-renderer"
        "chromium"
      ]
      [
        "services"
        "grafana-image-renderer"
        "settings"
        "browser"
        "path"
      ]
      (config: lib.getExe config.services.grafana-image-renderer.chromium)
    )
    (lib.mkRemovedOptionModule
      [
        "services"
        "grafana-image-renderer"
        "verbose"
      ]
      ''
        Use `services.grafana-image-renderer.settings.log.level = "debug"` instead.
      ''
    )
  ];

  options.services.grafana-image-renderer = {
    enable = lib.mkEnableOption "grafana-image-renderer";

    chromium = lib.mkOption {
      type = lib.types.package;
      description = ''
        The chromium to use for image rendering.
      '';
    };

    verbose = lib.mkEnableOption "verbosity for the service";

    provisionGrafana = lib.mkEnableOption "Grafana configuration for grafana-image-renderer";

    settings = lib.mkOption {
      type = lib.types.submodule {
        freeformType = format.type;
        imports = [
          ../../misc/assertions.nix
          (lib.mkRenamedOptionModule
            [
              "rendering"
              "width"
            ]
            [
              "browser"
              "min-width"
            ]
          )
          (lib.mkRenamedOptionModule
            [
              "rendering"
              "height"
            ]
            [
              "browser"
              "min-height"
            ]
          )
          (lib.mkRenamedOptionModule
            [
              "rendering"
              "args"
            ]
            [

              "browser"
              "flag"
            ]
          )
          (lib.mkChangedOptionModule
            [
              "service"
              "port"
            ]
            [
              "server"
              "addr"
            ]
            (config: "0.0.0.0:${toString config.service.port}")
          )
          (lib.mkRemovedOptionModule
            [
              "rendering"
              "mode"
            ]
            ''
              This option is obsolete.
            ''
          )
          (lib.mkRenamedOptionModule
            [
              "service"
              "logging"
            ]
            [
              "log"
            ]
          )
        ];

        options = {
          service = {
            port = lib.mkOption {
              type = lib.types.port;
              default = 8081;
          server.addr = lib.mkOption {
            type = lib.types.str;
            default = "localhost:8081";
            description = ''
                The TCP port to use for the rendering server.
              Listen address of the service.
            '';
          };
            logging.level = lib.mkOption {
              type = lib.types.enum [
                "error"
                "warning"
                "info"
                "debug"
              ];
              default = "info";
          browser.path = lib.mkOption {
            type = lib.types.path;
            default = lib.getExe pkgs.chromium;
            defaultText = lib.literalExpression "lib.getExe pkgs.chromium";
            description = ''
                The log-level of the {file}`grafana-image-renderer.service`-unit.
              Path to the executable of the chromium to use.
            '';
          };
        };
          rendering = {
            width = lib.mkOption {
              default = 1000;
              type = lib.types.ints.positive;
              description = ''
                Width of the PNG used to display the alerting graph.
              '';
            };
            height = lib.mkOption {
              default = 500;
              type = lib.types.ints.positive;
              description = ''
                Height of the PNG used to display the alerting graph.
              '';
            };
            mode = lib.mkOption {
              default = "default";
              type = lib.types.enum [
                "default"
                "reusable"
                "clustered"
              ];
              description = ''
                Rendering mode of `grafana-image-renderer`:

                - `default:` Creates on browser-instance
                  per rendering request.
                - `reusable:` One browser instance
                  will be started and reused for each rendering request.
                - `clustered:` allows to precisely
                  configure how many browser-instances are supposed to be used. The values
                  for that mode can be declared in `rendering.clustering`.
              '';
            };
            args = lib.mkOption {
              type = lib.types.listOf lib.types.str;
              default = [ "--no-sandbox" ];
              description = ''
                List of CLI flags passed to `chromium`.
              '';
            };
          };
        };
      };

      default = { };

      description = ''
        Configuration attributes for `grafana-image-renderer`.

        See <https://github.com/grafana/grafana-image-renderer/blob/ce1f81438e5f69c7fd7c73ce08bab624c4c92e25/default.json>
        for supported values.
      '';
    };
  };
@@ -120,39 +198,53 @@ in
    ];

    services.grafana.settings.rendering = lib.mkIf cfg.provisionGrafana {
      server_url = "http://localhost:${toString cfg.settings.service.port}/render";
      server_url = "http://${toString cfg.settings.server.addr}/render";
      callback_url = "http://${config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port}";
    };

    services.grafana-image-renderer.chromium = lib.mkDefault pkgs.chromium;

    services.grafana-image-renderer.settings = {
      rendering = lib.mapAttrs (lib.const lib.mkDefault) {
        chromeBin = "${cfg.chromium}/bin/chromium";
        verboseLogging = cfg.verbose;
        timezone = config.time.timeZone;
      };

      service = {
        logging.level = lib.mkIf cfg.verbose (lib.mkDefault "debug");
        metrics.enabled = lib.mkDefault false;
      };
      browser.timezone = lib.mkIf (config.time.timeZone != null) (lib.mkDefault config.time.timeZone);
    };

    systemd.services.grafana-image-renderer = {
      wantedBy = [ "multi-user.target" ];
      after = [ "network.target" ];
      wants = [ "network-online.target" ];
      after = [ "network-online.target" ];
      description = "Grafana backend plugin that handles rendering of panels & dashboards to PNGs using headless browser (Chromium/Chrome)";

      environment = {
        PUPPETEER_SKIP_CHROMIUM_DOWNLOAD = "true";
      };

      serviceConfig = {
        DynamicUser = true;
        PrivateTmp = true;
        ExecStart = "${pkgs.grafana-image-renderer}/bin/grafana-image-renderer server --config=${configFile}";
        ExecStart = "${lib.getExe pkgs.grafana-image-renderer} server ${format.generate cfg.settings}";
        Restart = "always";
        AmbientCapabilities = "";
        CapabilityBoundingSet = "";
        LockPersonality = true;
        MountAPIVFS = true;
        NoNewPrivileges = true;
        PrivateDevices = true;
        PrivateMounts = true;
        PrivateUsers = true;
        ProtectClock = true;
        ProtectControlGroups = "strict";
        ProtectHome = true;
        ProtectHostname = true;
        ProtectKernelLogs = true;
        ProtectKernelModules = true;
        ProtectKernelTunables = true;
        ProtectProc = "invisible";
        ProtectSystem = "full";
        RemoveIPC = true;
        RestrictAddressFamilies = [
          "AF_UNIX"
          "AF_INET"
          "AF_INET6"
        ];
        RestrictNamespaces = true;
        RestrictRealtime = true;
        RestrictSUIDSGID = true;
        SystemCallArchitectures = "native";
        UMask = 27;
      };
    };
  };
+1 −1
Original line number Diff line number Diff line
@@ -1267,7 +1267,7 @@ in
                No IP addresses are being tracked, only simple counters to track running instances, versions, dashboard and error counts.
                Counters are sent every 24 hours.
              '';
              default = true;
              default = false;
              type = types.bool;
            };

Loading