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.
This commit is contained in:
Arnout Engelen 2026-01-12 16:57:49 +01:00
commit f9576bd74d
No known key found for this signature in database
GPG key ID: 061107B0F74A6DAA
5 changed files with 126 additions and 132 deletions

View file

@ -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";

View file

@ -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 <<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
'';
};
};

View file

@ -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 <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;

View file

@ -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()

View file

@ -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 <<EOF
<Settings>
<file>${sdkjs}/common/Native/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>
<dictionaries>${dictionaries}</dictionaries>
</Settings>
cat >$out/bin/DoctRenderer.config <<EOF
<Settings>
<file>${sdkjs}/common/Native/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>
<dictionaries>${dictionaries}</dictionaries>
</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 = {