1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8let
9 cfg = config.services.stirling-pdf;
10in
11{
12 options.services.stirling-pdf = {
13 enable = lib.mkEnableOption "the stirling-pdf service";
14
15 package = lib.mkPackageOption pkgs "stirling-pdf" { };
16
17 environment = lib.mkOption {
18 type = lib.types.attrsOf (
19 lib.types.oneOf [
20 lib.types.str
21 lib.types.int
22 ]
23 );
24 default = { };
25 example = {
26 SERVER_PORT = 8080;
27 INSTALL_BOOK_AND_ADVANCED_HTML_OPS = "true";
28 };
29 description = ''
30 Environment variables for the stirling-pdf app.
31 See <https://github.com/Stirling-Tools/Stirling-PDF#customisation> for available options.
32 '';
33 };
34
35 environmentFiles = lib.mkOption {
36 type = lib.types.listOf lib.types.path;
37 default = [ ];
38 description = ''
39 Files containing additional environment variables to pass to Stirling PDF.
40 Secrets should be added in environmentFiles instead of environment.
41 '';
42 };
43 };
44
45 config = lib.mkIf cfg.enable {
46 systemd.services.stirling-pdf = {
47 environment = lib.mapAttrs (_: toString) cfg.environment;
48
49 # following https://docs.stirlingpdf.com/Installation/Unix%20Installation
50 path =
51 with pkgs;
52 [
53 # `which` is used to test command availability
54 # See https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/java/stirling/software/SPDF/config/ExternalAppDepConfig.java#L42
55 which
56 unpaper
57 libreoffice
58 qpdf
59 ocrmypdf
60 poppler-utils
61 unoconv
62 pngquant
63 tesseract
64 (python3.withPackages (
65 p: with p; [
66 weasyprint
67 opencv-python-headless
68 ]
69 ))
70 ghostscript_headless
71 ]
72 ++ lib.optional (cfg.environment.INSTALL_BOOK_AND_ADVANCED_HTML_OPS or "false" == "true") calibre;
73
74 wantedBy = [ "multi-user.target" ];
75
76 serviceConfig = {
77 BindReadOnlyPaths = [ "${pkgs.tesseract}/share/tessdata:/usr/share/tessdata" ];
78 CacheDirectory = "stirling-pdf";
79 Environment = [ "HOME=%S/stirling-pdf" ];
80 EnvironmentFile = cfg.environmentFiles;
81 ExecStart = lib.getExe cfg.package;
82 RuntimeDirectory = "stirling-pdf";
83 StateDirectory = "stirling-pdf";
84 SuccessExitStatus = 143;
85 User = "stirling-pdf";
86 WorkingDirectory = "/var/lib/stirling-pdf";
87
88 # Hardening
89 CapabilityBoundingSet = "";
90 DynamicUser = true;
91 LockPersonality = true;
92 NoNewPrivileges = true;
93 PrivateDevices = true;
94 PrivateUsers = true;
95 ProcSubset = "pid";
96 ProtectClock = true;
97 ProtectControlGroups = true;
98 ProtectHome = true;
99 ProtectHostname = true;
100 ProtectKernelLogs = true;
101 ProtectKernelModules = true;
102 ProtectKernelTunables = true;
103 ProtectProc = "invisible";
104 RestrictAddressFamilies = [
105 "AF_INET"
106 "AF_INET6"
107 "AF_UNIX"
108 ];
109 RestrictNamespaces = true;
110 RestrictRealtime = true;
111 SystemCallArchitectures = "native";
112 SystemCallFilter = [
113 "~@cpu-emulation @debug @keyring @mount @obsolete @privileged @clock @setuid @chown"
114 ];
115 UMask = "0077";
116 };
117 };
118 };
119
120 meta.maintainers = with lib.maintainers; [ DCsunset ];
121}