Unverified Commit 2b224f0e authored by r-vdp's avatar r-vdp
Browse files

nixos/systemd: allow using writeShellApplication for systemd unit scripts

parent 509b099f
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -62,6 +62,15 @@
  - The OCaml-based Xen Store can now be configured using  [`virtualisation.xen.store.settings`](#opt-virtualisation.xen.store.settings).
  - The `virtualisation.xen.bridge` options have been deprecated in this release cycle. Users who need network bridges are encouraged to set up their own networking configurations.

- A new option [`systemd.enableStrictShellChecks`](#opt-systemd.enableStrictShellChecks) has been added. When enabled, all systemd scripts generated by NixOS will
  be checked with [shellcheck](https://www.shellcheck.net) and any errors or warnings will cause the build to fail.
  This affects all scripts that have been created through the `script`, `reload`, `preStart`, `postStart`, `preStop` and `postStop` options for systemd services.
  This does not affect commandlines passed directly to `ExecStart`, `ExecReload`, `ExecStartPre`, `ExecStartPost`, `ExecStop` or `ExecStopPost`.
  It therefore also does not affect systemd units that are coming from packages and that are not defined through the NixOS config.
  This option is disabled by default, and although some services have already been fixed, it is still likely that you will encounter build failures when enabling this.
  We encourage people to enable this option when they are willing and able to submit fixes for potential build failures to nixpkgs.
  The option can also be enabled or disabled for individual services using the `enableStrictShellChecks` option on the service itself, which will take precedence over the global setting.

## New Modules {#sec-release-24.11-new-modules}

- [TaskChampion Sync-Server](https://github.com/GothenburgBitFactory/taskchampion-sync-server), a [Taskwarrior 3](https://taskwarrior.org/docs/upgrade-3/) sync server, replacing Taskwarrior 2's sync server named [`taskserver`](https://github.com/GothenburgBitFactory/taskserver).
+22 −7
Original line number Diff line number Diff line
@@ -386,18 +386,27 @@ in rec {
      ''}
    ''; # */

  makeJobScript = name: text:
  makeJobScript = { name, text, enableStrictShellChecks }:
    let
      scriptName = replaceStrings [ "\\" "@" ] [ "-" "_" ] (shellEscape name);
      out = (pkgs.writeShellScriptBin scriptName ''
      out = (
        if ! enableStrictShellChecks then
          pkgs.writeShellScriptBin scriptName ''
            set -e

            ${text}
      '').overrideAttrs (_: {
          ''
        else
          pkgs.writeShellApplication {
            name = scriptName;
            inherit text;
          }
      ).overrideAttrs (_: {
        # The derivation name is different from the script file name
        # to keep the script file name short to avoid cluttering logs.
        name = "unit-script-${scriptName}";
      });
    in "${out}/bin/${scriptName}";
    in lib.getExe out;

  unitConfig = { config, name, options, ... }: {
    config = {
@@ -448,10 +457,16 @@ in rec {
    };
  };

  serviceConfig = { name, config, ... }: {
  serviceConfig =
  let
    nixosConfig = config;
  in
  { name, lib, config, ... }: {
    config = {
      name = "${name}.service";
      environment.PATH = mkIf (config.path != []) "${makeBinPath config.path}:${makeSearchPathOutput "bin" "sbin" config.path}";

      enableStrictShellChecks = lib.mkOptionDefault nixosConfig.systemd.enableStrictShellChecks;
    };
  };

+39 −6
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ let
    concatMap
    filterOverrides
    isList
    literalExpression
    mergeEqualOption
    mkIf
    mkMerge
@@ -357,6 +358,14 @@ in rec {
        '';
      };

      enableStrictShellChecks = mkOption {
        type = types.bool;
        description = "Enable running shellcheck on the generated scripts for this unit.";
        # The default gets set in systemd-lib.nix because we don't have access to
        # the full NixOS config here.
        defaultText = literalExpression "config.systemd.enableStrictShellChecks";
      };

      script = mkOption {
        type = types.lines;
        default = "";
@@ -428,27 +437,51 @@ in rec {

    config = mkMerge [
      (mkIf (config.preStart != "") rec {
        jobScripts = makeJobScript "${name}-pre-start" config.preStart;
        jobScripts = makeJobScript {
          name = "${name}-pre-start";
          text = config.preStart;
          inherit (config) enableStrictShellChecks;
        };
        serviceConfig.ExecStartPre = [ jobScripts ];
      })
      (mkIf (config.script != "") rec {
        jobScripts = makeJobScript "${name}-start" config.script;
        jobScripts = makeJobScript {
          name = "${name}-start";
          text = config.script;
          inherit (config) enableStrictShellChecks;
        };
        serviceConfig.ExecStart = jobScripts + " " + config.scriptArgs;
      })
      (mkIf (config.postStart != "") rec {
        jobScripts = (makeJobScript "${name}-post-start" config.postStart);
        jobScripts = makeJobScript {
          name = "${name}-post-start";
          text = config.postStart;
          inherit (config) enableStrictShellChecks;
        };
        serviceConfig.ExecStartPost = [ jobScripts ];
      })
      (mkIf (config.reload != "") rec {
        jobScripts = makeJobScript "${name}-reload" config.reload;
        jobScripts = makeJobScript {
          name = "${name}-reload";
          text = config.reload;
          inherit (config) enableStrictShellChecks;
        };
        serviceConfig.ExecReload = jobScripts;
      })
      (mkIf (config.preStop != "") rec {
        jobScripts = makeJobScript "${name}-pre-stop" config.preStop;
        jobScripts = makeJobScript {
          name = "${name}-pre-stop";
          text = config.preStop;
          inherit (config) enableStrictShellChecks;
        };
        serviceConfig.ExecStop = jobScripts;
      })
      (mkIf (config.postStop != "") rec {
        jobScripts = makeJobScript "${name}-post-stop" config.postStop;
        jobScripts = makeJobScript {
          name = "${name}-post-stop";
          text = config.postStop;
          inherit (config) enableStrictShellChecks;
        };
        serviceConfig.ExecStopPost = jobScripts;
      })
    ];
+2 −0
Original line number Diff line number Diff line
@@ -197,6 +197,8 @@ in

    package = mkPackageOption pkgs "systemd" {};

    enableStrictShellChecks = mkEnableOption "running shellcheck on the generated scripts for systemd units.";

    units = mkOption {
      description = "Definition of systemd units; see {manpage}`systemd.unit(5)`.";
      default = {};