Browse Source

Add a NixOS module to configure webhooks that wait on FIFOs

master
Peter J. Jones 1 month ago
parent
commit
597d2858b4
Signed by: Peter Jones <pjones@devalot.com> GPG Key ID: 9DAFAA8D01941E49
4 changed files with 197 additions and 1 deletions
  1. 4
    0
      .envrc
  2. 165
    0
      nix/module.nix
  3. 1
    1
      personal-webhooks.nix
  4. 27
    0
      shell.nix

+ 4
- 0
.envrc View File

@@ -0,0 +1,4 @@
1
+# -*- sh -*-
2
+
3
+# Load in the shell.nix file:
4
+use nix

+ 165
- 0
nix/module.nix View File

@@ -0,0 +1,165 @@
1
+# A NixOS module that you can import to create hooks.
2
+{ config, lib, pkgs, ...}: with lib;
3
+
4
+let
5
+  cfg = config.services.personal-webhooks;
6
+  package = import ../default.nix { inherit pkgs; };
7
+  workingDir = "/var/lib/webhooks";
8
+
9
+  hookOptions = {
10
+    options = {
11
+      name = mkOption {
12
+        type = types.str;
13
+        description = "The name of this hook.";
14
+      };
15
+
16
+      script = mkOption {
17
+        type = types.path;
18
+        description = ''
19
+          The script to run on incoming JSON data.  The data will be
20
+          given to its STDIN.
21
+        '';
22
+      };
23
+
24
+      path = mkOption {
25
+        type = types.listOf types.package;
26
+        default = [ ];
27
+        description = "List of packages to put in PATH.";
28
+      };
29
+
30
+      user = mkOption {
31
+        type = types.str;
32
+        description = "The user to run the script as.";
33
+      };
34
+    };
35
+  };
36
+
37
+  hookToService = hook: {
38
+    description = "${hook.name} Webhook";
39
+    wantedBy = [ "multi-user.target" ];
40
+    after = [ "network.service" "personal-webhooks.service" ];
41
+    path = hook.path ++ (with pkgs; [ bash coreutils ]);
42
+
43
+    serviceConfig = {
44
+      WorkingDirectory = "~";
45
+      Restart = "always";
46
+      Type = "simple";
47
+      TimeoutStopSec = "10s";
48
+
49
+      PermissionsStartOnly = true;
50
+      User = hook.user;
51
+      UMask = "0007";
52
+    };
53
+
54
+    preStart = ''
55
+      mkdir -p ${cfg.pipesDirectory}/${hook.user}
56
+      chown -R ${hook.user}:${cfg.group} ${cfg.pipesDirectory}/${hook.user}
57
+      chmod -R 0711 ${cfg.pipesDirectory}
58
+      chmod -R 0755 ${cfg.pipesDirectory}/${hook.user}
59
+    '';
60
+
61
+    script = ''
62
+      export examples=$(find "${package.data}" -type d -name examples)
63
+
64
+      bash "$examples"/watchfifo.sh \
65
+      -f "${cfg.pipesDirectory}/${hook.user}/${hook.name}" \
66
+      -g "${cfg.group}" \
67
+      -- ${hook.script}
68
+    '';
69
+  };
70
+
71
+  mainService = {
72
+    personal-webhooks = {
73
+      description = "Personal Webhooks Server";
74
+      wantedBy = [ "multi-user.target" ];
75
+      after = [ "network.service" "postgresql.service" ];
76
+
77
+      serviceConfig = {
78
+        WorkingDirectory = "-${workingDir}";
79
+        ExecStart = "${cfg.package}/bin/webhooks -c ${cfg.configFile} server -p ${toString cfg.port}";
80
+        Restart = "always";
81
+        Type = "simple";
82
+
83
+        PermissionsStartOnly = true;
84
+        User = cfg.user;
85
+        Group = cfg.group;
86
+        UMask = "0077";
87
+      };
88
+
89
+      preStart = ''
90
+        ${pkgs.coreutils}/bin/mkdir -p ${workingDir} ${cfg.pipesDirectory}
91
+        ${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} ${workingDir} ${cfg.pipesDirectory}
92
+        ${pkgs.coreutils}/bin/chmod -R 0700 ${workingDir}
93
+        ${pkgs.coreutils}/bin/chmod -R 0770 ${cfg.pipesDirectory}
94
+      '';
95
+    };
96
+};
97
+in
98
+{
99
+  #### Interface:
100
+  options.services.personal-webhooks = {
101
+    enable = mkEnableOption "Personal Webhooks";
102
+
103
+    package = mkOption {
104
+      type = types.package;
105
+      default = package;
106
+      description = "The personal-webhooks package to use.";
107
+    };
108
+
109
+    port = mkOption {
110
+      type = types.int;
111
+      default = 8082;
112
+      description = "Port number for the webhooks server.";
113
+    };
114
+
115
+    user = mkOption {
116
+      type = types.str;
117
+      default = "webhooks";
118
+      description = "Webhooks server user.";
119
+    };
120
+
121
+    group = mkOption {
122
+      type = types.str;
123
+      default = "webhooks";
124
+      description = "Webhooks server group.";
125
+    };
126
+
127
+    pipesDirectory = mkOption {
128
+      type = types.path;
129
+      default = "/run/webhooks";
130
+      description = "Where FIFO pipes will live.";
131
+    };
132
+
133
+    configFile = mkOption {
134
+      type = types.path;
135
+      default = "${../examples/config.yml}";
136
+      description = "The configuration file to use.";
137
+    };
138
+
139
+    hooks = mkOption {
140
+      type = types.listOf (types.submodule hookOptions);
141
+      default = [ ];
142
+      description = "Hooks to configure.";
143
+    };
144
+  };
145
+
146
+  #### Implementation:
147
+  config = mkIf cfg.enable {
148
+    environment.systemPackages = [ cfg.package ];
149
+
150
+    users.extraUsers = optional (cfg.user == "webhooks")
151
+      { name = cfg.user;
152
+        description = "Webhooks user";
153
+        group = cfg.group;
154
+        isSystemUser = true;
155
+      };
156
+
157
+    users.extraGroups = optional (cfg.group == "webhooks")
158
+      { name = cfg.group;
159
+      };
160
+
161
+    systemd.services =
162
+      foldl' (x: y: x // {"webhook-${y.name}" = hookToService y;})
163
+             mainService cfg.hooks;
164
+  };
165
+}

+ 1
- 1
personal-webhooks.nix View File

@@ -7,7 +7,7 @@
7 7
 }:
8 8
 mkDerivation {
9 9
   pname = "personal-webhooks";
10
-  version = "0.1.0.0";
10
+  version = "0.1.0.1";
11 11
   src = ./.;
12 12
   isLibrary = true;
13 13
   isExecutable = true;

+ 27
- 0
shell.nix View File

@@ -0,0 +1,27 @@
1
+{ pkgs ? (import <nixpkgs> {}).pkgs
2
+}:
3
+
4
+let
5
+  nix-hs-src = fetchGit {
6
+    url = "https://code.devalot.com/pjones/nix-hs.git";
7
+    rev = "4a9ea2c8c6712ae3cb5892bc74dc051906535238";
8
+  };
9
+
10
+  nix-hs = (import "${nix-hs-src}/default.nix" {inherit pkgs;});
11
+
12
+in
13
+
14
+pkgs.mkShell {
15
+  buildInputs = with pkgs; [
16
+
17
+    # Haskell Dependencies:
18
+    haskellPackages.ghc
19
+    haskellPackages.cabal-install
20
+
21
+    # For IDEs:
22
+    nix-hs
23
+    haskellPackages.hoogle
24
+    haskellPackages.hlint
25
+    # haskellPackages.cabal-dependency-licenses
26
+  ];
27
+}

Loading…
Cancel
Save