Unverified Commit f9576bd7 authored by Arnout Engelen's avatar Arnout Engelen
Browse files

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.
parent e4bae1bd
Loading
Loading
Loading
Loading
+11 −11
Original line number Diff line number Diff line
@@ -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";
+76 −77
Original line number Diff line number Diff line
{
  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 <<EOF
      <Settings>
        <file>${x2t.components.sdkjs}/common/Native/native.js</file>
        <file>${x2t.components.sdkjs}/common/Native/jquery_native.js</file>
        <allfonts>$out/converter/AllFonts.js</allfonts>
        <file>${x2t.components.web-apps}/vendor/xregexp/xregexp-all-min.js</file>
        <sdkjs>${x2t.components.sdkjs}</sdkjs>
        <dictionaries>${x2t.components.dictionaries}</dictionaries>
      </Settings>
    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
        '';
      };
    };

+27 −0
Original line number Diff line number Diff line
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 <sstream>
 #include "ApplicationFonts.h"
 #include "../common/File.h"
 #include "../common/Directory.h"
@@ -1845,6 +1846,14 @@ std::vector<std::wstring> 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;
+0 −13
Original line number Diff line number Diff line
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()
+12 −31
Original line number Diff line number Diff line
@@ -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,11 +822,10 @@ 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 <<EOF
    cat >$out/bin/DoctRenderer.config <<EOF
      <Settings>
        <file>${sdkjs}/common/Native/native.js</file>
            <file>${sdkjs}//common/Native/jquery_native.js</file>
        <file>${sdkjs}/common/Native/jquery_native.js</file>
        <allfonts>${allfonts}/converter/AllFonts.js</allfonts>
        <file>${web-apps}/vendor/xregexp/xregexp-all-min.js</file>
        <sdkjs>${sdkjs}</sdkjs>
@@ -847,11 +833,6 @@ buildCoreComponent "X2tConverter/build/Qt" {
      </Settings>
    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 = {