grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / web-servers / fcgiwrap.nix
blob36a327b9ab9f99ffe2cccb0e599a79767979df9d
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   forEachInstance = f: flip mapAttrs' config.services.fcgiwrap.instances (
7     name: cfg: nameValuePair "fcgiwrap-${name}" (f cfg)
8   );
10 in {
11   imports = forEach [
12     "enable"
13     "user"
14     "group"
15     "socketType"
16     "socketAddress"
17     "preforkProcesses"
18   ] (attr: mkRemovedOptionModule [ "services" "fcgiwrap" attr ] ''
19       The global shared fcgiwrap instance is no longer supported due to
20       security issues.
21       Isolated instances should instead be configured through
22       `services.fcgiwrap.instances.*'.
23   '');
25   options.services.fcgiwrap.instances = mkOption {
26     description = "Configuration for fcgiwrap instances.";
27     default = { };
28     type = types.attrsOf (types.submodule ({ config, ... }: { options = {
29       process.prefork = mkOption {
30         type = types.ints.positive;
31         default = 1;
32         description = "Number of processes to prefork.";
33       };
35       process.user = mkOption {
36         type = types.nullOr types.str;
37         default = null;
38         description = ''
39           User as which this instance of fcgiwrap will be run.
40           Set to `null` (the default) to use a dynamically allocated user.
41         '';
42       };
44       process.group = mkOption {
45         type = types.nullOr types.str;
46         default = null;
47         description = "Group as which this instance of fcgiwrap will be run.";
48       };
50       socket.type = mkOption {
51         type = types.enum [ "unix" "tcp" "tcp6" ];
52         default = "unix";
53         description = "Socket type: 'unix', 'tcp' or 'tcp6'.";
54       };
56       socket.address = mkOption {
57         type = types.str;
58         default = "/run/fcgiwrap-${config._module.args.name}.sock";
59         example = "1.2.3.4:5678";
60         description = ''
61           Socket address.
62           In case of a UNIX socket, this should be its filesystem path.
63         '';
64       };
66       socket.user = mkOption {
67         type = types.nullOr types.str;
68         default = null;
69         description = ''
70           User to be set as owner of the UNIX socket.
71         '';
72       };
74       socket.group = mkOption {
75         type = types.nullOr types.str;
76         default = null;
77         description = ''
78           Group to be set as owner of the UNIX socket.
79         '';
80       };
82       socket.mode = mkOption {
83         type = types.nullOr types.str;
84         default = if config.socket.type == "unix" then "0600" else null;
85         defaultText = literalExpression ''
86           if config.socket.type == "unix" then "0600" else null
87         '';
88         description = ''
89           Mode to be set on the UNIX socket.
90           Defaults to private to the socket's owner.
91         '';
92       };
93     }; }));
94   };
96   config = {
97     assertions = concatLists (mapAttrsToList (name: cfg: [
98       {
99         assertion = cfg.socket.type == "unix" -> cfg.socket.user != null;
100         message = "Socket owner is required for the UNIX socket type.";
101       }
102       {
103         assertion = cfg.socket.type == "unix" -> cfg.socket.group != null;
104         message = "Socket owner is required for the UNIX socket type.";
105       }
106       {
107         assertion = cfg.socket.user != null -> cfg.socket.type == "unix";
108         message = "Socket owner can only be set for the UNIX socket type.";
109       }
110       {
111         assertion = cfg.socket.group != null -> cfg.socket.type == "unix";
112         message = "Socket owner can only be set for the UNIX socket type.";
113       }
114       {
115         assertion = cfg.socket.mode != null -> cfg.socket.type == "unix";
116         message = "Socket mode can only be set for the UNIX socket type.";
117       }
118     ]) config.services.fcgiwrap.instances);
120     systemd.services = forEachInstance (cfg: {
121       after = [ "nss-user-lookup.target" ];
122       wantedBy = optional (cfg.socket.type != "unix") "multi-user.target";
124       serviceConfig = {
125         ExecStart = ''
126           ${pkgs.fcgiwrap}/sbin/fcgiwrap ${cli.toGNUCommandLineShell {} ({
127             c = cfg.process.prefork;
128           } // (optionalAttrs (cfg.socket.type != "unix") {
129             s = "${cfg.socket.type}:${cfg.socket.address}";
130           }))}
131         '';
132       } // (if cfg.process.user != null then {
133         User = cfg.process.user;
134         Group = cfg.process.group;
135       } else {
136         DynamicUser = true;
137       });
138     });
140     systemd.sockets = forEachInstance (cfg: mkIf (cfg.socket.type == "unix") {
141       wantedBy = [ "sockets.target" ];
142       socketConfig = {
143         ListenStream = cfg.socket.address;
144         SocketUser = cfg.socket.user;
145         SocketGroup = cfg.socket.group;
146         SocketMode = cfg.socket.mode;
147       };
148     });
149   };