From f9576bd74df7b866104aff2e710d9cc648d73777 Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Mon, 12 Jan 2026 16:57:49 +0100 Subject: [PATCH] nixos/onlyoffice: declaratively manage fonts This refactor has several additional advantages: * simplify by moving logic from service startup to build time, also making the service more stateless because they can now be loaded from the nix store instead of keeping this state in /var/lib/onlyoffice * improve disk usage by reducing the need for copying over symlinking This also unlocks further simplifications: it removes the need to have `pkgs/by-name/x2/x2t` as a separate package and brings us closer to not needing the fhs wrapper for the converter and docservice. Those are for the future, though. --- .../modules/services/web-apps/onlyoffice.nix | 22 +-- .../on/onlyoffice-documentserver/package.nix | 153 +++++++++--------- .../core-fontengine-custom-fonts-paths.patch | 27 ++++ .../x2/x2t/doctrenderer-config-dir.patch | 13 -- pkgs/by-name/x2/x2t/package.nix | 43 ++--- 5 files changed, 126 insertions(+), 132 deletions(-) create mode 100644 pkgs/by-name/x2/x2t/core-fontengine-custom-fonts-paths.patch delete mode 100644 pkgs/by-name/x2/x2t/doctrenderer-config-dir.patch diff --git a/nixos/modules/services/web-apps/onlyoffice.nix b/nixos/modules/services/web-apps/onlyoffice.nix index 10c0ed1b779c..526ef9269645 100644 --- a/nixos/modules/services/web-apps/onlyoffice.nix +++ b/nixos/modules/services/web-apps/onlyoffice.nix @@ -133,13 +133,6 @@ in virtualHosts.${cfg.hostname} = { locations = { - # resources that are generated and thus cannot be taken from the cfg.package yet: - "~ ^(\\/[\\d]+\\.[\\d]+\\.[\\d]+[\\.|-][\\w]+)?\\/(sdkjs/common/AllFonts.js)$".extraConfig = '' - proxy_pass http://onlyoffice-docservice/$2$3; - ''; - "~ ^(\\/[\\d]+\\.[\\d]+\\.[\\d]+[\\.|-][\\w]+)?\\/(fonts/.*)$".extraConfig = '' - proxy_pass http://onlyoffice-docservice/$2$3; - ''; # /etc/nginx/includes/ds-docservice.conf # disable caching for api.js "~ ^(\\/[\\d]+\\.[\\d]+\\.[\\d]+[\\.|-][\\w]+)?\\/(web-apps\\/apps\\/api\\/documents\\/api\\.js)$".extraConfig = @@ -278,7 +271,7 @@ in serviceConfig = { # needs to be ran wrapped in FHS for now # because the default config refers to many FHS paths - ExecStart = "${cfg.package.fhs}/bin/onlyoffice-wrapper ${cfg.package.fileconverter}/bin/fileconverter /run/onlyoffice/config"; + ExecStart = "${cfg.package.fhs}/bin/onlyoffice-wrapper ${cfg.package.fileconverter}/bin/fileconverter"; Group = "onlyoffice"; Restart = "always"; RuntimeDirectory = "onlyoffice"; @@ -336,8 +329,10 @@ in ' /run/onlyoffice/config/default.json | sponge /run/onlyoffice/config/default.json chmod u+w /run/onlyoffice/config/production-linux.json - jq '.FileConverter.converter.x2tPath = "${cfg.x2t}/bin/x2t"' \ - /run/onlyoffice/config/production-linux.json | sponge /run/onlyoffice/config/production-linux.json + jq ' + .log.filePath = "/run/onlyoffice/config/log4js/production.json" | + .FileConverter.converter.x2tPath = "${cfg.package.x2t-with-fonts-and-themes}/bin/x2t" + ' /run/onlyoffice/config/production-linux.json | sponge /run/onlyoffice/config/production-linux.json chmod u+w /run/onlyoffice/config/log4js/production.json jq '.categories.default.level = "${cfg.loglevel}"' \ @@ -360,8 +355,13 @@ in ]; requires = [ "postgresql.target" ]; wantedBy = [ "multi-user.target" ]; + environment = { + NODE_CONFIG_DIR = "/run/onlyoffice/config"; + NODE_DISABLE_COLORS = "1"; + NODE_ENV = "production-linux"; + }; serviceConfig = { - ExecStart = "${cfg.package.fhs}/bin/onlyoffice-wrapper ${cfg.package.docservice}/bin/docservice /run/onlyoffice/config"; + ExecStart = "${cfg.package.fhs}/bin/onlyoffice-wrapper ${cfg.package.docservice}/bin/docservice"; ExecStartPre = [ onlyoffice-prestart ]; Group = "onlyoffice"; Restart = "always"; diff --git a/pkgs/by-name/on/onlyoffice-documentserver/package.nix b/pkgs/by-name/on/onlyoffice-documentserver/package.nix index 59bf1a6b4483..61f9d7e50ae8 100644 --- a/pkgs/by-name/on/onlyoffice-documentserver/package.nix +++ b/pkgs/by-name/on/onlyoffice-documentserver/package.nix @@ -1,21 +1,21 @@ { buildFHSEnv, buildNpmPackage, - corefonts, dpkg, - dejavu_fonts, fetchFromGitHub, fetchurl, gcc-unwrapped, lib, - liberation_ttf_v1, lndir, nixosTests, pkg-config, + runCommand, stdenv, vips, writeScript, x2t, + + extra-fonts ? [ ], }: let @@ -76,6 +76,59 @@ let ln -s ${docservice}/lib/node_modules/coauthoring $out/lib/node_modules/DocService ''; }); + + # https://github.com/ONLYOFFICE/document-server-package/blob/master/common/documentserver/bin/documentserver-generate-allfonts.sh.m4 + x2t-with-fonts-and-themes = runCommand "x2t-with-fonts-and-themes" { } '' + mkdir -p $out/web + mkdir -p $out/converter + mkdir -p $out/images + mkdir -p $out/fonts + + echo Generating fonts + export CUSTOM_FONTS_PATHS=${lib.concatStringsSep ":" extra-fonts} + ${x2t.components.allfontsgen}/bin/allfontsgen \ + --input=${x2t.components.core-fonts} \ + --allfonts-web=$out/web/AllFonts.js \ + --allfonts=$out/converter/AllFonts.js \ + --images=$out/images \ + --selection=$out/converter/font_selection.bin \ + --output-web=$out/fonts \ + --use-system=true + + mkdir -p $out/bin + cp ${x2t}/bin/x2t $out/bin + cat >$out/bin/DoctRenderer.config < + ${x2t.components.sdkjs}/common/Native/native.js + ${x2t.components.sdkjs}/common/Native/jquery_native.js + $out/converter/AllFonts.js + ${x2t.components.web-apps}/vendor/xregexp/xregexp-all-min.js + ${x2t.components.sdkjs} + ${x2t.components.dictionaries} + + EOF + + echo Generating presentation themes + # creates temporary files next to sources... + mkdir working + cp ${x2t.components.sdkjs}/slide/themes/src/* working + ${x2t.components.allthemesgen}/bin/allthemesgen \ + --converter-dir="$out/bin"\ + --src="working"\ + --output="$out/images" + ${x2t.components.allthemesgen}/bin/allthemesgen \ + --converter-dir="$out/bin"\ + --src="working"\ + --output="$out/images"\ + --postfix="ios"\ + --params="280,224" + ${x2t.components.allthemesgen}/bin/allthemesgen \ + --converter-dir="$out/bin"\ + --src="working"\ + --output="$out/images"\ + --postfix="android"\ + --params="280,224" + ''; # var/www/onlyoffice/documentserver/server/DocService/docservice onlyoffice-documentserver = stdenv.mkDerivation { pname = "onlyoffice-documentserver"; @@ -104,10 +157,20 @@ let cp -r common/documentserver-example/welcome $out/var/www/onlyoffice/documentserver-example mkdir -p $out/var/www/onlyoffice/documentserver - ln -s ${x2t.components.web-apps} $out/var/www/onlyoffice/documentserver/web-apps - # copying instead of linking for now because we want to inject - # AllFonts.js in here: - cp -r ${x2t.components.sdkjs} $out/var/www/onlyoffice/documentserver/sdkjs + + # equivalent of usr/bin/documentserver-flush-cache.sh, + # busts cache also when fonts collection changes + mkdir $out/var/www/onlyoffice/documentserver/web-apps + ${lndir}/bin/lndir -silent ${x2t.components.web-apps} $out/var/www/onlyoffice/documentserver/web-apps + mv $out/var/www/onlyoffice/documentserver/web-apps/apps/api/documents/api.js{,.orig} + sed -e "s/{{HASH_POSTFIX}}/$(basename $out | cut -d '-' -f 1)/" $out/var/www/onlyoffice/documentserver/web-apps/apps/api/documents/api.js.orig > $out/var/www/onlyoffice/documentserver/web-apps/apps/api/documents/api.js + + ln -s ${x2t-with-fonts-and-themes}/fonts $out/var/www/onlyoffice/documentserver/fonts + + mkdir -p $out/var/www/onlyoffice/documentserver/sdkjs + ${lndir}/bin/lndir -silent ${x2t.components.sdkjs} $out/var/www/onlyoffice/documentserver/sdkjs + ln -s ${x2t-with-fonts-and-themes}/web/AllFonts.js $out/var/www/onlyoffice/documentserver/sdkjs/common/AllFonts.js + ${lndir}/bin/lndir -silent ${x2t-with-fonts-and-themes}/images $out/var/www/onlyoffice/documentserver/sdkjs/common/Images # we don't currently support sdkjs plugins in NixOS # https://github.com/ONLYOFFICE/build_tools/blob/master/scripts/deploy_server.py#L130 @@ -116,20 +179,22 @@ let mkdir -p $out/var/www/onlyoffice/documentserver/server/schema cp -r ${server-src}/schema/* $out/var/www/onlyoffice/documentserver/server/schema - mkdir -p $out/var/www/onlyoffice/documentserver/server/FileConverter/bin ## required for bwrap --bind chmod u+w $out/var mkdir -p $out/var/lib/onlyoffice - chmod u+w $out/var/www/onlyoffice/documentserver - mkdir $out/var/www/onlyoffice/documentserver/fonts ''; # stripping self extracting javascript binaries likely breaks them dontStrip = true; passthru = { - inherit fileconverter common docservice; + inherit + x2t-with-fonts-and-themes + common + docservice + fileconverter + ; tests = nixosTests.onlyoffice; fhs = buildFHSEnv { name = "onlyoffice-wrapper"; @@ -137,11 +202,6 @@ let targetPkgs = pkgs: [ gcc-unwrapped.lib onlyoffice-documentserver - - # fonts - corefonts - dejavu_fonts - liberation_ttf_v1 fileconverter ]; @@ -152,68 +212,7 @@ let extraBwrapArgs = [ "--bind var/lib/onlyoffice/ var/lib/onlyoffice/" - "--bind var/lib/onlyoffice/documentserver/sdkjs/common/ var/www/onlyoffice/documentserver/sdkjs/common/" - "--bind var/lib/onlyoffice/documentserver/sdkjs/slide/themes/ var/www/onlyoffice/documentserver/sdkjs/slide/themes/" - "--bind var/lib/onlyoffice/documentserver/fonts/ var/www/onlyoffice/documentserver/fonts/" - "--bind var/lib/onlyoffice/documentserver/server/FileConverter/bin/ var/www/onlyoffice/documentserver/server/FileConverter/bin/" ]; - - runScript = writeScript "onlyoffice-documentserver-run-script" '' - export NODE_CONFIG_DIR=$2 - export NODE_DISABLE_COLORS=1 - export NODE_ENV=production-linux - - if [[ $1 == *"docservice" ]]; then - mkdir -p var/www/onlyoffice/documentserver/sdkjs/slide/themes/ - # symlinking themes/src breaks discovery in allfontsgen - rm -rf var/www/onlyoffice/documentserver/sdkjs/slide/themes/src - cp -r ${onlyoffice-documentserver}/var/www/onlyoffice/documentserver/sdkjs/slide/themes/src var/www/onlyoffice/documentserver/sdkjs/slide/themes/ - chmod -R u+w var/www/onlyoffice/documentserver/sdkjs/slide/themes/ - - # onlyoffice places generated files in those directores - rm -rf var/www/onlyoffice/documentserver/sdkjs/common/* - ${lndir}/bin/lndir -silent ${onlyoffice-documentserver}/var/www/onlyoffice/documentserver/sdkjs/common/ var/www/onlyoffice/documentserver/sdkjs/common/ - rm -rf var/www/onlyoffice/documentserver/server/FileConverter/bin/* - ${lndir}/bin/lndir -silent ${onlyoffice-documentserver}/var/www/onlyoffice/documentserver/server/FileConverter/bin/ var/www/onlyoffice/documentserver/server/FileConverter/bin/ - - # https://github.com/ONLYOFFICE/document-server-package/blob/master/common/documentserver/bin/documentserver-generate-allfonts.sh.m4 - # TODO --use-system doesn't actually appear to make a difference? - echo -n Generating AllFonts.js, please wait... - "${x2t.components.allfontsgen}/bin/allfontsgen"\ - --input="${x2t.components.core-fonts}"\ - --allfonts-web="var/www/onlyoffice/documentserver/sdkjs/common/AllFonts.js"\ - --allfonts="var/www/onlyoffice/documentserver/server/FileConverter/bin/AllFonts.js"\ - --images="var/www/onlyoffice/documentserver/sdkjs/common/Images"\ - --selection="var/www/onlyoffice/documentserver/server/FileConverter/bin/font_selection.bin"\ - --output-web="var/www/onlyoffice/documentserver/fonts"\ - --use-system="true" - echo Done - - # TODO x2t brings its on DoctRenderer.config, so it wouldn't pick up the new fonts: - echo -n Generating presentation themes, please wait... - "${x2t.components.allthemesgen}/bin/allthemesgen"\ - --converter-dir="${x2t}/bin"\ - --src="var/www/onlyoffice/documentserver/sdkjs/slide/themes"\ - --output="var/www/onlyoffice/documentserver/sdkjs/common/Images" - - "${x2t.components.allthemesgen}/bin/allthemesgen"\ - --converter-dir="${x2t}/bin"\ - --src="var/www/onlyoffice/documentserver/sdkjs/slide/themes"\ - --output="var/www/onlyoffice/documentserver/sdkjs/common/Images"\ - --postfix="ios"\ - --params="280,224" - - "${x2t.components.allthemesgen}/bin/allthemesgen"\ - --converter-dir="${x2t}/bin"\ - --src="var/www/onlyoffice/documentserver/sdkjs/slide/themes"\ - --output="var/www/onlyoffice/documentserver/sdkjs/common/Images"\ - --postfix="android"\ - --params="280,224" - echo Done - fi - - exec $1 - ''; }; }; diff --git a/pkgs/by-name/x2/x2t/core-fontengine-custom-fonts-paths.patch b/pkgs/by-name/x2/x2t/core-fontengine-custom-fonts-paths.patch new file mode 100644 index 000000000000..e043e77eb8c0 --- /dev/null +++ b/pkgs/by-name/x2/x2t/core-fontengine-custom-fonts-paths.patch @@ -0,0 +1,27 @@ +diff --git a/DesktopEditor/fontengine/ApplicationFonts.cpp b/DesktopEditor/fontengine/ApplicationFonts.cpp +index ed1a01fb1b..ee071f9ebe 100644 +--- a/DesktopEditor/fontengine/ApplicationFonts.cpp ++++ b/DesktopEditor/fontengine/ApplicationFonts.cpp +@@ -29,6 +29,7 @@ + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ ++#include + #include "ApplicationFonts.h" + #include "../common/File.h" + #include "../common/Directory.h" +@@ -1845,6 +1846,14 @@ std::vector CApplicationFonts::GetSetupFontFiles(const bool& bIsUs + std::wstring custom_fonts_path = NSSystemUtils::GetEnvVariable(L"CUSTOM_FONTS_PATH"); + if (!custom_fonts_path.empty()) + NSDirectory::GetFiles2(custom_fonts_path, _array, true); ++ ++ std::wstring custom_fonts_paths = NSSystemUtils::GetEnvVariable(L"CUSTOM_FONTS_PATHS"); ++ if (!custom_fonts_paths.empty()) { ++ std::wistringstream stream(custom_fonts_paths); ++ while (std::getline(stream, custom_fonts_path, L':')) { ++ NSDirectory::GetFiles2(custom_fonts_path, _array, true); ++ } ++ } + #endif + + return _array; diff --git a/pkgs/by-name/x2/x2t/doctrenderer-config-dir.patch b/pkgs/by-name/x2/x2t/doctrenderer-config-dir.patch deleted file mode 100644 index a27ff140b112..000000000000 --- a/pkgs/by-name/x2/x2t/doctrenderer-config-dir.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/DesktopEditor/doctrenderer/doctrenderer.cpp b/DesktopEditor/doctrenderer/doctrenderer.cpp -index ac24efa8b2..f6de72cc2a 100644 ---- a/DesktopEditor/doctrenderer/doctrenderer.cpp -+++ b/DesktopEditor/doctrenderer/doctrenderer.cpp -@@ -238,7 +238,7 @@ namespace NSDoctRenderer - public: - CDoctRenderer_Private(const std::wstring& sAllFontsPath = L"") : CDoctRendererConfig() - { -- LoadConfig(NSFile::GetProcessDirectory(), sAllFontsPath); -+ LoadConfig(NSFile::GetProcessDirectory() + L"/../etc", sAllFontsPath); - m_pDrawingFile = NULL; - } - ~CDoctRenderer_Private() diff --git a/pkgs/by-name/x2/x2t/package.nix b/pkgs/by-name/x2/x2t/package.nix index 8bb46f0acc87..79c1f78f0e03 100644 --- a/pkgs/by-name/x2/x2t/package.nix +++ b/pkgs/by-name/x2/x2t/package.nix @@ -137,8 +137,6 @@ let # workaround for https://github.com/NixOS/nixpkgs/issues/477803 nodejs = nodejs_22; - #src = /home/aengelen/d/onlyoffice/documentserver/web-apps; - #sourceRoot = "/build/web-apps/build"; src = fetchFromGitHub { owner = "ONLYOFFICE"; repo = "web-apps"; @@ -183,11 +181,6 @@ let cp -r ../deploy/web-apps $out - ## see usr/bin/documentserver-flush-cache.sh - chmod u+w $out/apps/api/documents - substituteInPlace $out/apps/api/documents/api.js \ - --replace-fail '{{HASH_POSTFIX}}' "$(basename $out | cut -d '-' -f 1)" - runHook postInstall ''; }); @@ -362,6 +355,7 @@ let graphics = buildCoreComponent "DesktopEditor/graphics/pro" { patches = [ ./cximage-types.patch + ./core-fontengine-custom-fonts-paths.patch ]; buildInputs = [ unicodeConverter @@ -470,12 +464,6 @@ let chmod u+w $BUILDRT/Common/3dParty/apple/libetonyek/src/lib cp $BUILDRT/Common/3dParty/apple/headers/* $BUILDRT/Common/3dParty/apple/libetonyek/src/lib ''; - installPhase = '' - runHook preInstall - mkdir -p $out/lib - mv ../build/lib/*/* $out/lib - runHook postInstall - ''; doCheck = true; passthru.tests = buildCoreTests "Apple/test" { buildInputs = [ @@ -601,7 +589,6 @@ let patches = [ # https://github.com/ONLYOFFICE/core/pull/1631 ./doctrenderer-format-security.patch - ./doctrenderer-config-dir.patch ./doctrenderer-v8-iterator.patch ./fontengine-format-security.patch ./v8_updates.patch @@ -731,7 +718,7 @@ let runHook preInstall mkdir -p $out/bin - cp $BUILDRT/build/bin/*/* $BUILDRT/build/bin/*/*/* $out/bin + find $BUILDRT/build -type f -exec cp {} $out/bin \; runHook postInstall ''; @@ -757,7 +744,7 @@ let runHook preInstall mkdir -p $out/bin - cp $BUILDRT/build/bin/*/* $BUILDRT/build/bin/*/*/* $out/bin + find $BUILDRT/build -type f -exec cp {} $out/bin \; runHook postInstall ''; @@ -835,23 +822,17 @@ buildCoreComponent "X2tConverter/build/Qt" { mkdir -p $out/bin find $BUILDRT/build -type f -exec cp {} $out/bin \; - mkdir $out/etc - cat >$out/etc/DoctRenderer.config < - ${sdkjs}/common/Native/native.js - ${sdkjs}//common/Native/jquery_native.js - ${allfonts}/converter/AllFonts.js - ${web-apps}/vendor/xregexp/xregexp-all-min.js - ${sdkjs} - ${dictionaries} - + cat >$out/bin/DoctRenderer.config < + ${sdkjs}/common/Native/native.js + ${sdkjs}/common/Native/jquery_native.js + ${allfonts}/converter/AllFonts.js + ${web-apps}/vendor/xregexp/xregexp-all-min.js + ${sdkjs} + ${dictionaries} + EOF - # TODO when allthemesgen invokes x2t as the converter, it - # hard-codes expecting DoctRenderer.config in the same dir - # the x2t binary is located: - ln -s $out/etc/DoctRenderer.config $out/bin/DoctRenderer.config - runHook postInstall ''; passthru.tests = {