diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index a080e04ac603..6022cd4912d1 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -251,6 +251,9 @@ - `services.paperless` now installs `paperless-manage` as a normal system package instead of creating a symlink in `/var/lib/paperless`. `paperless-manage` now also changes to the appropriate user when being executed. +- The `gotenberg` package has been updated to 8.16.0, which brings breaking changes to the configuration from version 8.13.0. See the [upstream release notes](https://github.com/gotenberg/gotenberg/releases/tag/v8.13.0) + for that release to get all the details. The `services.gotenberg` module has been updated appropriately to ensure your configuration is valid with this new release. + - `asusd` has been upgraded to version 6 which supports multiple aura devices. To account for this, the single `auraConfig` configuration option has been replaced with `auraConfigs` which is an attribute set of config options per each device. The config files may also be now specified as either source files or text strings; to account for this you will need to specify that `text` is used for your existing configs, e.g.: ```diff -services.asusd.asusdConfig = '''file contents''' diff --git a/nixos/modules/services/misc/gotenberg.nix b/nixos/modules/services/misc/gotenberg.nix index e92e11b50c71..6d59b905dbea 100644 --- a/nixos/modules/services/misc/gotenberg.nix +++ b/nixos/modules/services/misc/gotenberg.nix @@ -16,14 +16,26 @@ let "--chromium-max-queue-size=${toString cfg.chromium.maxQueueSize}" "--libreoffice-restart-after=${toString cfg.libreoffice.restartAfter}" "--libreoffice-max-queue-size=${toString cfg.libreoffice.maxQueueSize}" - "--pdfengines-engines=${lib.concatStringsSep "," cfg.pdfEngines}" + "--pdfengines-merge-engines=${lib.concatStringsSep "," cfg.pdfEngines.merge}" + "--pdfengines-convert-engines=${lib.concatStringsSep "," cfg.pdfEngines.convert}" + "--pdfengines-read-metadata-engines=${lib.concatStringsSep "," cfg.pdfEngines.readMetadata}" + "--pdfengines-write-metadata-engines=${lib.concatStringsSep "," cfg.pdfEngines.writeMetadata}" + "--api-download-from-allow-list=${cfg.downloadFrom.allowList}" + "--api-download-from-max-retry=${toString cfg.downloadFrom.maxRetries}" ] ++ optional cfg.enableBasicAuth "--api-enable-basic-auth" ++ optional cfg.chromium.autoStart "--chromium-auto-start" ++ optional cfg.chromium.disableJavascript "--chromium-disable-javascript" ++ optional cfg.chromium.disableRoutes "--chromium-disable-routes" ++ optional cfg.libreoffice.autoStart "--libreoffice-auto-start" - ++ optional cfg.libreoffice.disableRoutes "--libreoffice-disable-routes"; + ++ optional cfg.libreoffice.disableRoutes "--libreoffice-disable-routes" + ++ optional cfg.pdfEngines.disableRoutes "--pdfengines-disable-routes" + ++ optional ( + cfg.downloadFrom.denyList != null + ) "--api-download-from-deny-list=${cfg.downloadFrom.denyList}" + ++ optional cfg.downloadFrom.disable "--api-disable-download-from" + ++ optional (cfg.bodyLimit != null) "--api-body-limit=${cfg.bodyLimit}" + ++ lib.optionals (cfg.extraArgs != [ ]) cfg.extraArgs; inherit (lib) mkEnableOption @@ -51,6 +63,12 @@ in description = "Port on which the API should listen."; }; + bindIP = mkOption { + type = types.nullOr types.str; + default = "127.0.0.1"; + description = "Port the API listener should bind to. Set to 0.0.0.0 to listen on all available IPs."; + }; + timeout = mkOption { type = types.nullOr types.str; default = "30s"; @@ -74,6 +92,12 @@ in ''; }; + bodyLimit = mkOption { + type = types.nullOr types.str; + default = null; + description = "Sets the max limit for `multipart/form-data` requests. Accepts values like '5M', '20G', etc."; + }; + extraFontPackages = mkOption { type = types.listOf types.package; default = [ ]; @@ -108,6 +132,29 @@ in }; }; + downloadFrom = { + allowList = mkOption { + type = types.nullOr types.str; + default = ".*"; + description = "Allow these URLs to be used in the `downloadFrom` API field. Accepts a regular expression."; + }; + denyList = mkOption { + type = types.nullOr types.str; + default = null; + description = "Deny accepting URLs from these domains in the `downloadFrom` API field. Accepts a regular expression."; + }; + maxRetries = mkOption { + type = types.int; + default = 4; + description = "The maximum amount of times to retry downloading a file specified with `downloadFrom`."; + }; + disable = mkOption { + type = types.bool; + default = false; + description = "Whether to disable the ability to download files for conversion from outside sources."; + }; + }; + libreoffice = { package = mkPackageOption pkgs "libreoffice" { }; @@ -136,28 +183,61 @@ in }; }; - pdfEngines = mkOption { - type = types.listOf ( - types.enum [ - "pdftk" + pdfEngines = { + merge = mkOption { + type = types.listOf ( + types.enum [ + "qpdf" + "pdfcpu" + "pdftk" + ] + ); + default = [ "qpdf" - "libreoffice-pdfengine" - "exiftool" "pdfcpu" - ] - ); - default = [ - "pdftk" - "qpdf" - "libreoffice-pdfengine" - "exiftool" - "pdfcpu" - ]; - description = '' - PDF engines to enable. Each one can be used to perform a specific task. - See [the documentation](https://gotenberg.dev/docs/configuration#pdf-engines) for more details. - Defaults to all possible PDF engines. - ''; + "pdftk" + ]; + description = "PDF Engines to use for merging files."; + }; + convert = mkOption { + type = types.listOf ( + types.enum [ + "libreoffice-pdfengine" + ] + ); + default = [ + "libreoffice-pdfengine" + ]; + description = "PDF Engines to use for converting files."; + }; + readMetadata = mkOption { + type = types.listOf ( + types.enum [ + "exiftool" + ] + ); + default = [ + "exiftool" + ]; + description = "PDF Engines to use for reading metadata from files."; + }; + writeMetadata = mkOption { + type = types.listOf ( + types.enum [ + "exiftool" + ] + ); + default = [ + "exiftool" + ]; + description = "PDF Engines to use for writing metadata to files."; + }; + + disableRoutes = mkOption { + type = types.bool; + default = false; + description = "Disable routes related to PDF engines."; + }; }; logLevel = mkOption { @@ -196,6 +276,15 @@ in See `services.gotenberg.enableBasicAuth` for the names of those variables. ''; } + { + assertion = !(lib.isList cfg.pdfEngines); + message = '' + Setting `services.gotenberg.pdfEngines` to a list is now deprecated. + Use the new `pdfEngines.mergeEngines`, `pdfEngines.convertEngines`, `pdfEngines.readMetadataEngines`, and `pdfEngines.writeMetadataEngines` settings instead. + + The previous option was using a method that is now deprecated by upstream. + ''; + } ]; systemd.services.gotenberg = { @@ -209,12 +298,20 @@ in FONTCONFIG_FILE = pkgs.makeFontsConf { fontDirectories = [ pkgs.liberation_ttf_v2 ] ++ cfg.extraFontPackages; }; + # Needed for LibreOffice to work correctly. + # https://github.com/NixOS/nixpkgs/issues/349123#issuecomment-2418330936 + HOME = "/run/gotenberg"; }; serviceConfig = { Type = "simple"; DynamicUser = true; ExecStart = "${lib.getExe cfg.package} ${lib.escapeShellArgs args}"; + # Needed for LibreOffice to work correctly. + # See above issue comment. + WorkingDirectory = "/run/gotenberg"; + RuntimeDirectory = "gotenberg"; + # Hardening options PrivateDevices = true; PrivateIPC = true; @@ -243,6 +340,7 @@ in SystemCallFilter = [ "@sandbox" "@system-service" + "@chown" ]; SystemCallArchitectures = "native"; diff --git a/pkgs/by-name/go/gotenberg/package.nix b/pkgs/by-name/go/gotenberg/package.nix index b4f105360c38..cfd1d797ad33 100644 --- a/pkgs/by-name/go/gotenberg/package.nix +++ b/pkgs/by-name/go/gotenberg/package.nix @@ -12,6 +12,7 @@ makeFontsConf, liberation_ttf_v2, exiftool, + pdfcpu, nixosTests, nix-update-script, }: @@ -23,19 +24,21 @@ let in buildGoModule rec { pname = "gotenberg"; - version = "8.9.1"; + version = "8.16.0"; src = fetchFromGitHub { owner = "gotenberg"; repo = "gotenberg"; tag = "v${version}"; - hash = "sha256-y54DtOYIzFAk05TvXFcLdStfAXim3sVHBkW+R8CrtMM="; + hash = "sha256-m8aDhfcUa3QFr+7hzlQFL2wPfcx5RE+3dl5RHzWwau0="; }; - vendorHash = "sha256-BYcdqZ8TNEG6popRt+Dg5xW5Q7RmYvdlV+niUNenRG0="; + vendorHash = "sha256-EM+Rpo4Zf+aqA56aFeuQ0tbvpTgZhmfv+B7qYI6PXWc="; postPatch = '' find ./pkg -name '*_test.go' -exec sed -i -e 's#/tests#${src}#g' {} \; + substituteInPlace pkg/gotenberg/fs_test.go \ + --replace-fail "/tmp" "/build" ''; nativeBuildInputs = [ makeBinaryWrapper ]; @@ -52,6 +55,7 @@ buildGoModule rec { pdftk qpdf unoconv + pdfcpu mktemp jre' ]; @@ -62,6 +66,7 @@ buildGoModule rec { export QPDF_BIN_PATH=${getExe qpdf} export UNOCONVERTER_BIN_PATH=${getExe unoconv} export EXIFTOOL_BIN_PATH=${getExe exiftool} + export PDFCPU_BIN_PATH=${getExe pdfcpu} # LibreOffice needs all of these set to work properly export LIBREOFFICE_BIN_PATH=${libreoffice'} export FONTCONFIG_FILE=${fontsConf} @@ -70,7 +75,14 @@ buildGoModule rec { ''; # These tests fail with a panic, so disable them. - checkFlags = [ "-skip=^TestChromiumBrowser_(screenshot|pdf)$" ]; + checkFlags = + let + skippedTests = [ + "TestChromiumBrowser_(screenshot|pdf)" + "TestNewContext" + ]; + in + [ "-skip=^${builtins.concatStringsSep "$|^" skippedTests}$" ]; preFixup = '' wrapProgram $out/bin/gotenberg \ @@ -78,6 +90,7 @@ buildGoModule rec { --set QPDF_BIN_PATH "${getExe qpdf}" \ --set UNOCONVERTER_BIN_PATH "${getExe unoconv}" \ --set EXIFTOOL_BIN_PATH "${getExe exiftool}" \ + --set PDFCPU_BIN_PATH "${getExe pdfcpu}" \ --set JAVA_HOME "${jre'}" '';