silx: 2.1.1 -> 2.1.2 (#361612)
[NixPkgs.git] / nixos / modules / services / misc / gotenberg.nix
blobed8629a7fa46f899c2d4f699507fbc9c03d89af9
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
7 let
8   cfg = config.services.gotenberg;
10   args =
11     [
12       "--api-port=${toString cfg.port}"
13       "--api-timeout=${cfg.timeout}"
14       "--api-root-path=${cfg.rootPath}"
15       "--log-level=${cfg.logLevel}"
16       "--chromium-max-queue-size=${toString cfg.chromium.maxQueueSize}"
17       "--libreoffice-restart-after=${toString cfg.libreoffice.restartAfter}"
18       "--libreoffice-max-queue-size=${toString cfg.libreoffice.maxQueueSize}"
19       "--pdfengines-engines=${lib.concatStringsSep "," cfg.pdfEngines}"
20     ]
21     ++ optional cfg.enableBasicAuth "--api-enable-basic-auth"
22     ++ optional cfg.chromium.autoStart "--chromium-auto-start"
23     ++ optional cfg.chromium.disableJavascript "--chromium-disable-javascript"
24     ++ optional cfg.chromium.disableRoutes "--chromium-disable-routes"
25     ++ optional cfg.libreoffice.autoStart "--libreoffice-auto-start"
26     ++ optional cfg.libreoffice.disableRoutes "--libreoffice-disable-routes";
28   inherit (lib)
29     mkEnableOption
30     mkPackageOption
31     mkOption
32     types
33     mkIf
34     optional
35     optionalAttrs
36     ;
39   options = {
40     services.gotenberg = {
41       enable = mkEnableOption "Gotenberg, a stateless API for PDF files";
43       # Users can override only gotenberg, libreoffice and chromium if they want to (eg. ungoogled-chromium, different LO version, etc)
44       # Don't allow setting the qpdf, pdftk, or unoconv paths, as those are very stable
45       # and there's only one version of each.
46       package = mkPackageOption pkgs "gotenberg" { };
48       port = mkOption {
49         type = types.port;
50         default = 3000;
51         description = "Port on which the API should listen.";
52       };
54       timeout = mkOption {
55         type = types.nullOr types.str;
56         default = "30s";
57         description = "Timeout for API requests.";
58       };
60       rootPath = mkOption {
61         type = types.str;
62         default = "/";
63         description = "Root path for the Gotenberg API.";
64       };
66       enableBasicAuth = mkOption {
67         type = types.bool;
68         default = false;
69         description = ''
70           HTTP Basic Authentication.
72           If you set this, be sure to set `GOTENBERG_API_BASIC_AUTH_USERNAME`and `GOTENBERG_API_BASIC_AUTH_PASSWORD`
73           in your `services.gotenberg.environmentFile` file.
74         '';
75       };
77       extraFontPackages = mkOption {
78         type = types.listOf types.package;
79         default = [ ];
80         description = "Extra fonts to make available.";
81       };
83       chromium = {
84         package = mkPackageOption pkgs "chromium" { };
86         maxQueueSize = mkOption {
87           type = types.int;
88           default = 0;
89           description = "Maximum queue size for chromium-based conversions. Setting to 0 disables the limit.";
90         };
92         autoStart = mkOption {
93           type = types.bool;
94           default = false;
95           description = "Automatically start chromium when Gotenberg starts. If false, Chromium will start on the first conversion request that uses it.";
96         };
98         disableJavascript = mkOption {
99           type = types.bool;
100           default = false;
101           description = "Disable Javascript execution.";
102         };
104         disableRoutes = mkOption {
105           type = types.bool;
106           default = false;
107           description = "Disable all routes allowing Chromium-based conversion.";
108         };
109       };
111       libreoffice = {
112         package = mkPackageOption pkgs "libreoffice" { };
114         restartAfter = mkOption {
115           type = types.int;
116           default = 10;
117           description = "Restart LibreOffice after this many conversions. Setting to 0 disables this feature.";
118         };
120         maxQueueSize = mkOption {
121           type = types.int;
122           default = 0;
123           description = "Maximum queue size for LibreOffice-based conversions. Setting to 0 disables the limit.";
124         };
126         autoStart = mkOption {
127           type = types.bool;
128           default = false;
129           description = "Automatically start LibreOffice when Gotenberg starts. If false, Chromium will start on the first conversion request that uses it.";
130         };
132         disableRoutes = mkOption {
133           type = types.bool;
134           default = false;
135           description = "Disable all routes allowing LibreOffice-based conversion.";
136         };
137       };
139       pdfEngines = mkOption {
140         type = types.listOf (
141           types.enum [
142             "pdftk"
143             "qpdf"
144             "libreoffice-pdfengine"
145             "exiftool"
146             "pdfcpu"
147           ]
148         );
149         default = [
150           "pdftk"
151           "qpdf"
152           "libreoffice-pdfengine"
153           "exiftool"
154           "pdfcpu"
155         ];
156         description = ''
157           PDF engines to enable. Each one can be used to perform a specific task.
158           See [the documentation](https://gotenberg.dev/docs/configuration#pdf-engines) for more details.
159           Defaults to all possible PDF engines.
160         '';
161       };
163       logLevel = mkOption {
164         type = types.enum [
165           "error"
166           "warn"
167           "info"
168           "debug"
169         ];
170         default = "info";
171         description = "The logging level for Gotenberg.";
172       };
174       environmentFile = mkOption {
175         type = types.nullOr types.path;
176         default = null;
177         description = "Environment file to load extra environment variables from.";
178       };
180       extraArgs = mkOption {
181         type = types.listOf types.str;
182         default = [ ];
183         description = "Any extra command-line flags to pass to the Gotenberg service.";
184       };
185     };
186   };
188   config = mkIf cfg.enable {
189     assertions = [
190       {
191         assertion = cfg.enableBasicAuth -> cfg.environmentFile != null;
192         message = ''
193           When enabling HTTP Basic Authentication with `services.gotenberg.enableBasicAuth`,
194           you must provide an environment file via `services.gotenberg.environmentFile` with the appropriate environment variables set in it.
196           See `services.gotenberg.enableBasicAuth` for the names of those variables.
197         '';
198       }
199     ];
201     systemd.services.gotenberg = {
202       description = "Gotenberg API server";
203       after = [ "network.target" ];
204       wantedBy = [ "multi-user.target" ];
205       path = [ cfg.package ];
206       environment = {
207         LIBREOFFICE_BIN_PATH = "${cfg.libreoffice.package}/lib/libreoffice/program/soffice.bin";
208         CHROMIUM_BIN_PATH = lib.getExe cfg.chromium.package;
209         FONTCONFIG_FILE = pkgs.makeFontsConf {
210           fontDirectories = [ pkgs.liberation_ttf_v2 ] ++ cfg.extraFontPackages;
211         };
212       };
213       serviceConfig = {
214         Type = "simple";
215         DynamicUser = true;
216         ExecStart = "${lib.getExe cfg.package} ${lib.escapeShellArgs args}";
218         # Hardening options
219         PrivateDevices = true;
220         PrivateIPC = true;
221         PrivateUsers = true;
223         ProtectClock = true;
224         ProtectControlGroups = true;
225         ProtectHome = true;
226         ProtectHostname = true;
227         ProtectKernelLogs = true;
228         ProtectKernelModules = true;
229         ProtectKernelTunables = true;
230         ProtectProc = "invisible";
231         ProcSubset = "pid";
233         RestrictAddressFamilies = [
234           "AF_UNIX"
235           "AF_INET"
236           "AF_INET6"
237           "AF_NETLINK"
238         ];
239         RestrictNamespaces = true;
240         RestrictRealtime = true;
242         LockPersonality = true;
243         MemoryDenyWriteExecute = true;
245         SystemCallFilter = [
246           "@system-service"
247           "~@privileged"
248         ];
249         SystemCallArchitectures = "native";
251         UMask = 77;
252       } // optionalAttrs (cfg.environmentFile != null) { EnvironmentFile = cfg.environmentFile; };
253     };
254   };
256   meta.maintainers = with lib.maintainers; [ pyrox0 ];