summaryrefslogtreecommitdiffstats
path: root/krebs/3modules/systemd.nix
blob: fc92da128c4f0933ad314997db9eaf9a7eebf3df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
{ config, pkgs, lib, ... }: let {

  slib = import ../../lib/lib.nix { inherit lib; };

  body.options.krebs.systemd.services = lib.mkOption {
    default = {};
    type = lib.types.attrsOf (lib.types.submodule (cfg_: let
      serviceName = cfg_.config._module.args.name;
      cfg = config.systemd.services.${serviceName} // cfg_.config;
    in {
      options = {
        credentialPaths = lib.mkOption {
          default =
            lib.sort
              lib.lessThan
              (lib.filter
                slib.types.absolute-pathname.check
                (map
                  (slib.compose [ slib.maybeHead (builtins.match "[^:]*:(.*)") ])
                  (lib.toList cfg.serviceConfig.LoadCredential)));
          readOnly = true;
        };
        credentialUnitName = lib.mkOption {
          default = "trigger-${slib.systemd.encodeName serviceName}";
          readOnly = true;
        };
        restartIfCredentialsChange = lib.mkOption {
          default = false;
          description = ''
            Whether to restart the service whenever any of its credentials
            change.  Only credentials with an absolute path in LoadCredential=
            are supported.
          '';
          type = lib.types.bool;
        };
      };
    }));
  };

  body.config.systemd = lib.mkMerge (lib.mapAttrsToList (serviceName: cfg: {
    paths.${cfg.credentialUnitName} = {
      wantedBy = [ "multi-user.target" ];
      pathConfig.PathChanged = cfg.credentialPaths;
    };
    services.${cfg.credentialUnitName} = {
      serviceConfig = {
        Type = "oneshot";
        StateDirectory = "credentials";
        ExecStart = pkgs.writeDash "${cfg.credentialUnitName}.sh" ''
          set -efu

          PATH=${lib.makeBinPath [
            pkgs.coreutils
            pkgs.diffutils
            pkgs.systemd
          ]}

          cache=/var/lib/credentials/${slib.shell.escape serviceName}.sha1sum
          tmpfile=$(mktemp -t "$(basename "$cache")".XXXXXXXX)
          trap 'rm -f "$tmpfile"' EXIT

          sha1sum ${toString cfg.credentialPaths} > "$tmpfile"
          if test -f "$cache" && cmp -s "$tmpfile" "$cache"; then
            exit
          fi
          mv "$tmpfile" "$cache"

          systemctl restart ${slib.shell.escape serviceName}
        '';
      };
    };
  }) config.krebs.systemd.services);
}