summaryrefslogtreecommitdiffstats
path: root/krebs/3modules/permown.nix
blob: 63adb223614b42c61012ffe37796f88670e6fb16 (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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
with import <stockholm/lib>;
{ config, pkgs, ... }: {

  options.krebs.permown = mkOption {
    default = {};
    type = types.attrsOf (types.submodule ({ config, ... }: {
      options = {
        directory-mode = mkOption {
          default = "=rwx";
          type = types.str; # TODO
        };
        file-mode = mkOption {
          default = "=rw";
          type = types.str; # TODO
        };
        group = mkOption {
          apply = x: if x == null then "" else x;
          default = null;
          type = types.nullOr types.groupname;
        };
        owner = mkOption {
          type = types.username;
        };
        path = mkOption {
          default = config._module.args.name;
          type = types.absolute-pathname;
        };
        umask = mkOption {
          default = "0027";
          type = types.file-mode;
        };
      };
    }));
  };

  config = let
    plans = attrValues config.krebs.permown;
  in mkIf (plans != []) {

    system.activationScripts.permown = let
      mkdir = plan: /* sh */ ''
        ${pkgs.coreutils}/bin/mkdir -p ${shell.escape plan.path}
      '';
    in concatMapStrings mkdir plans;

    systemd.services = genAttrs' plans (plan: {
      name = "permown.${replaceStrings ["/"] ["_"] plan.path}";
      value = {
        environment = {
          DIR_MODE = plan.directory-mode;
          FILE_MODE = plan.file-mode;
          OWNER_GROUP = "${plan.owner}:${plan.group}";
          ROOT_PATH = plan.path;
        };
        path = [
          pkgs.coreutils
          pkgs.findutils
          pkgs.inotifyTools
        ];
        serviceConfig = {
          ExecStart = pkgs.writeDash "permown" ''
            set -efu

            find "$ROOT_PATH" -exec chown -h "$OWNER_GROUP" {} +
            find "$ROOT_PATH" -type d -exec chmod "$DIR_MODE" {} +
            find "$ROOT_PATH" -type f -exec chmod "$FILE_MODE" {} +

            paths=/tmp/paths
            rm -f "$paths"
            mkfifo "$paths"

            inotifywait -mrq -e CREATE --format %w%f "$ROOT_PATH" > "$paths" &
            inotifywaitpid=$!

            trap cleanup EXIT
            cleanup() {
              kill "$inotifywaitpid"
            }

            while read -r path; do
              if test -d "$path"; then
                cleanup
                exec "$0" "$@"
              fi
              chown -h "$OWNER_GROUP" "$path"
              if test -f "$path"; then
                chmod "$FILE_MODE" "$path"
              fi
            done < "$paths"
          '';
          PrivateTemp = true;
          Restart = "always";
          RestartSec = 10;
          UMask = plan.umask;
        };
        wantedBy = [ "multi-user.target" ];
      };
    });

  };

}