grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / web-apps / collabora-online.nix
blob122674b67110c7732f83c9247bb097c0048f4d09
2   config,
3   lib,
4   pkgs,
5   utils,
6   ...
7 }:
9 let
10   cfg = config.services.collabora-online;
12   freeformType = lib.types.attrsOf ((pkgs.formats.json { }).type) // {
13     description = ''
14       `coolwsd.xml` configuration type, used to override values in the default configuration.
16       Attribute names correspond to XML tags unless prefixed with `@`. Nested attribute sets
17       correspond to nested XML tags. Attribute prefixed with `@` correspond to XML attributes. E.g.,
18       `{ storage.wopi."@allow" = true; }` in Nix corresponds to
19       `<storage><wopi allow="true"/></storage>` in `coolwsd.xml`, or `--o:storage.wopi[@allow]=true`
20       in the command line.
22       Arrays correspond to multiple elements with the same tag name. E.g.
23       `{ host = [ '''127\.0\.0\.1''' "::1" ]; }` in Nix corresponds to
24       ```xml
25       <net><post_allow>
26         <host>127\.0\.0\.1</host>
27         <host>::1</host>
28       </post_allow></net>
29       ```
30       in `coolwsd.xml`, or
31       `--o:net.post_allow.host[0]='127\.0\.0\.1 --o:net.post_allow.host[1]=::1` in the command line.
33       Null values could be used to remove an element from the default configuration.
34     '';
35   };
37   configFile =
38     pkgs.runCommandLocal "coolwsd.xml"
39       {
40         nativeBuildInputs = [
41           pkgs.jq
42           pkgs.yq-go
43         ];
44         userConfig = builtins.toJSON { config = cfg.settings; };
45         passAsFile = [ "userConfig" ];
46       }
47       # Merge the cfg.settings into the default coolwsd.xml.
48       # See https://github.com/CollaboraOnline/online/issues/10049.
49       ''
50         yq --input-format=xml \
51            --xml-attribute-prefix=@ \
52            --output-format=json \
53            ${cfg.package}/etc/coolwsd/coolwsd.xml \
54            > ./default_coolwsd.json
56         jq '.[0] * .[1] | del(..|nulls)' \
57            --slurp \
58            ./default_coolwsd.json \
59            $userConfigPath \
60            > ./merged.json
62         yq --output-format=xml \
63            --xml-attribute-prefix=@ \
64            ./merged.json \
65            > $out
66       '';
69   options.services.collabora-online = {
70     enable = lib.mkEnableOption "collabora-online";
72     package = lib.mkPackageOption pkgs "Collabora Online" { default = "collabora-online"; };
74     port = lib.mkOption {
75       type = lib.types.port;
76       default = 9980;
77       description = "Listening port";
78     };
80     settings = lib.mkOption {
81       type = freeformType;
82       default = { };
83       description = ''
84         Configuration for Collabora Online WebSocket Daemon, see
85         <https://sdk.collaboraonline.com/docs/installation/Configuration.html>, or
86         <https://github.com/CollaboraOnline/online/blob/master/coolwsd.xml.in> for the default
87         configuration.
88       '';
89     };
91     aliasGroups = lib.mkOption {
92       type = lib.types.listOf (
93         lib.types.submodule {
94           options = {
95             host = lib.mkOption {
96               type = lib.types.str;
97               example = "scheme://hostname:port";
98               description = "Hostname to allow or deny.";
99             };
101             aliases = lib.mkOption {
102               type = lib.types.listOf lib.types.str;
103               default = [ ];
104               example = [
105                 "scheme://aliasname1:port"
106                 "scheme://aliasname2:port"
107               ];
108               description = "A list of regex pattern of aliasname.";
109             };
110           };
111         }
112       );
113       default = [ ];
114       description = "Alias groups to use.";
115     };
117     extraArgs = lib.mkOption {
118       type = lib.types.listOf lib.types.str;
119       default = [ ];
120       description = "Extra arguments to pass to the service.";
121     };
122   };
124   config = lib.mkIf cfg.enable {
125     services.collabora-online.settings = {
126       child_root_path = lib.mkDefault "/var/lib/cool/child-roots";
127       sys_template_path = lib.mkDefault "/var/lib/cool/systemplate";
129       file_server_root_path = lib.mkDefault "${config.services.collabora-online.package}/share/coolwsd";
131       # Use mount namespaces instead of setcap'd coolmount/coolforkit.
132       mount_namespaces = lib.mkDefault true;
134       # By default, use dummy self-signed certificates provided for testing.
135       ssl.ca_file_path = lib.mkDefault "${config.services.collabora-online.package}/etc/coolwsd/ca-chain.cert.pem";
136       ssl.cert_file_path = lib.mkDefault "${config.services.collabora-online.package}/etc/coolwsd/cert.pem";
137       ssl.key_file_path = lib.mkDefault "${config.services.collabora-online.package}/etc/coolwsd/key.pem";
138     };
140     users.users.cool = {
141       isSystemUser = true;
142       group = "cool";
143     };
144     users.groups.cool = { };
146     systemd.services.coolwsd-systemplate-setup = {
147       description = "Collabora Online WebSocket Daemon Setup";
148       wantedBy = [ "multi-user.target" ];
149       serviceConfig = {
150         ExecStart = utils.escapeSystemdExecArgs [
151           "${cfg.package}/bin/coolwsd-systemplate-setup"
152           "/var/lib/cool/systemplate"
153           "${cfg.package.libreoffice}/lib/collaboraoffice"
154         ];
155         RemainAfterExit = true;
156         StateDirectory = "cool";
157         Type = "oneshot";
158         User = "cool";
159       };
160     };
162     systemd.services.coolwsd = {
163       description = "Collabora Online WebSocket Daemon";
164       wantedBy = [ "multi-user.target" ];
165       after = [
166         "network.target"
167         "coolwsd-systemplate-setup.service"
168       ];
170       environment = builtins.listToAttrs (
171         lib.imap1 (n: ag: {
172           name = "aliasgroup${toString n}";
173           value = lib.concatStringsSep "," ([ ag.host ] ++ ag.aliases);
174         }) cfg.aliasGroups
175       );
177       serviceConfig = {
178         ExecStart = utils.escapeSystemdExecArgs (
179           [
180             "${cfg.package}/bin/coolwsd"
181             "--config-file=${configFile}"
182             "--port=${toString cfg.port}"
183             "--use-env-vars"
184             "--version"
185           ]
186           ++ cfg.extraArgs
187         );
188         KillMode = "mixed";
189         KillSignal = "SIGINT";
190         LimitNOFILE = "infinity:infinity";
191         Restart = "always";
192         StateDirectory = "cool";
193         TimeoutStopSec = 120;
194         User = "cool";
195       };
196     };
197   };
199   meta.maintainers = [ lib.maintainers.xzfc ];