{ config, lib, pkgs, ... }: { passthru = { systemdAnalyze = lib.mapAttrs (s: _: let # NOTE: systemd-analyze needs /run/systemd; bubblewrap is used to provide a fake environment. bwrapFlags = (lib.escapeShellArgs [ "--dev" "/dev" "--bind" "/nix" "/nix" "--tmpfs" "/tmp" "--tmpfs" "/run/systemd" "--bind" "/bin" "/bin" "--bind" "${config.system.build.etc}/etc/systemd/system/${s}.service" "/etc/systemd/system/${s}.service" ]) + " --tmpfs \"$HOME\""; in { security = pkgs.stdenv.mkDerivation (finalAttrs: { name = "systemd-analyze-security-${s}-output"; preferLocalBuild = true; dontUnpack = true; dontBuild = true; dontFixup = true; installPhase = '' runHook preInstall if [ -f '${config.system.build.etc}/etc/systemd/system/${s}.service' ]; then mkdir -p "$(dirname "$out")" ${lib.getExe pkgs.bubblewrap} ${bwrapFlags} ${lib.getExe' pkgs.systemd "systemd-analyze"} security --offline true ${config.system.build.etc}/etc/systemd/system/${s}.service > "$out" || touch "$out" else touch "$out" fi runHook postInstall ''; passthru.finalScore = lib.pipe finalAttrs.finalPackage [ lib.readFile (x: if x == "" then null else lib.pipe x [ lib.trim (lib.splitString "\n") lib.last (lib.match ".*([0-9])\\.([0-9]).*") (digits: (lib.toIntBase10 (lib.head digits)) + (lib.toIntBase10 (lib.last digits)) * 0.1) ]) ]; }); verify = pkgs.runCommandLocal "systemd-analyze-verify-${s}-output" { } '' mkdir -p "$(dirname "$out")" ${lib.getExe pkgs.bubblewrap} ${bwrapFlags} ${lib.getExe' pkgs.systemd "systemd-analyze"} verify --man=no ${config.system.build.etc}/etc/systemd/system/${s}.service |& tee "$out" ''; }) config.systemd.services; systemdSecurityScores = # NOTE: force all 'security' instantiations to build in parallel builtins.seq (builtins.readDir (pkgs.linkFarm "systemd-analyze-security-all-outputs" (lib.mapAttrs (s: _: config.passthru.systemdAnalyze.${s}.security) config.systemd.services))) lib.mapAttrs (s: _: config.passthru.systemdAnalyze.${s}.security.finalScore) config.systemd.services; }; }