+++
Categories = ["Development","Systems Administration"]
Tags = ["Development","Systems Administration"]
Description = "How to build LibreofficeOnline against stock LibreOffice on Debian Stretch"
date = "2017-07-07T12:44:53-04:00"
title = "Building LibreOffice Online for Debian"
type = "post"
weight = 1
draft = false

+++

DISCLAIMER: I never did proceed with this project beyond building the packages. I can offer no helpful support regarding getting it running.

LibreOffice Online is a very cool project by the fine people at [Collabora](https://www.collaboraoffice.com/code/) to bring the LibreOffice core functionality into a web browser. In effect, it's a Free Software version of the Google Docs suite of productivity tools, allowing one or many people to edit and save documents in a browser.

The software builds on the LibreOffice core code, and currently is only distributed as a Docker image, obtainable from the link above. However, my BLSE2 platform does not support Docker now, or at any time in the foreseeable future [aside: maybe I'll write my reasoning out, one day], and is based entirely around Debian and the idea of "use the package manager as much as possible". So I set out to build everything myself.

This however was no small task - there's precious little usable information in any one place on how to do this, especially not from the official Collabora site that just wants you to use the Docker image [re-aside: yea, that's one reason I hate Docker...]. Luckily, a GitHub user by the name of `m-jowlett` has written about his processes in a log [over at his GitHub page](https://gist.github.com/m-jowett/0f28bff952737f210574fc3b2efaa01a) [`m-jowett/log.md` should this link eventually rot]. His guide is however extremely rough, as well as using Ubuntu and building for integration with another project featuring OwnCloud. It however gave me most of what I needed to get going with this, including help integrating the final package with my OwnCloud instance(s).

As mentioned briefly above, my philosophy in BLSE2 is "use a package" - this is a core feature of Debian, and one of the most solid examples of quality forethought in design in the Free Software world. By separating applications from their libraries, you keep security updates easy and with minimal administrative work. As such, I always choose to build a package if possible, and luckily with LibreOffice Online I can. And it's right there in the repo! A huge win in my mind, especially considering my initial fear of a program distributed as a Docker Image [re-re-aside: poor dependency life-cycle management and monolithic software bundles - another reason I hate Docker; but I digress]. As this is a brand-new project and I'm a keen `dist-upgrade`er, I've gone with the brand-new Stretch (9.0) release in the `amd64` arch - you should probably be running the same, but 32-bit will work too.

```
$ cat /etc/debian_version
9.0
$ uname -a
Linux libreoffice-online 4.9.0-3-amd64 #1 SMP Debian 4.9.30-2+deb9u2 (2017-06-26) x86_64 GNU/Linux
```

So without further ado, here's how to build LibreOffice Online on Debian Stretch!

## Installing the [Easy] Dependencies

The `m-jowlett` guide lists a couple of dependencies: `libpng12-dev`, `libcap-dev`, `libtool`, `m4`, and `automake`, and I'll add in `fakeroot`, `debhelper`, `dh-systemd`, and the `build-essential` metapackage to build the Debian packages, as well as `unixodbc-dev` which is required by the POCO build process below. The only one to cause problems in Stretch is `libpng12-dev`: we need the `libpng-dev` package instead, which installs `libpng16-dev`. The version bump doesn't seem to affect anything negatively, however. And of course, we need the full `libreoffice` suite and it's build-deps installed as well, `python-polib`, `nodejs-legacy` and `node-jake` to grab some modules during the build, as well as `libghc-zlib-bindings-dev` and `libghc-zlib-dev` which pulls in `ghc`.

```
$ sudo apt install libpng-dev libcap-dev libtool m4 automake fakeroot debhelper dh-systemd build-essential unixodbc-dev libreoffice python-polib nodejs-legacy node-jake libghc-zlib-bindings-dev libghc-zlib-dev
$ sudo apt build-dep libreoffice
```

## Building POCO

The one dependency that is hard is `libpoco-dev`. LibreOffice Online makes extensive use of JSON processing using `libpoco`. However, there's a problem: the author of JSON decided it was a bright idea to troll(?) the Free Software community, and added a problematic line to his otherwise-MIT licensed code. "The Software shall be used for Good, not Evil." As a result, JSON doesn't fit the [Debian Free Software Guidelines and isn't present in any Debian packages](https://wiki.debian.org/qa.debian.org/jsonevil), and while Debian Stretch contains `libpoco` of a version we require, the extremely-critical-to-LOOL JSON parsing library is disabled in the code. So, we have to build the `libpoco` packages ourselves with JSON support, and then install them as dependencies.

First, we start with a bare Stretch machine with the above dependencies installed and several GB of free space, and then create a directory to contain our `libpoco` build. We then download both the Debian source package and the Git repository fetching the same version branch.

```
$ mkdir ~/libpoco
$ cd ~/libpoco/
$ apt-get source libpoco-dev
$ git clone --recursive --depth 1 --branch poco-1.7.6-release https://github.com/pocoproject/poco.git
$ ls
poco  poco-1.7.6+dfsg1  poco_1.7.6+dfsg1-5.debian.tar.xz  poco_1.7.6+dfsg1-5.dsc  poco_1.7.6+dfsg1.orig.tar.bz2
```

Note the `+dfsg` tag to the source packages - this is indicative that the Debian maintainer modified the package to comply with the DFSG. Luckily though, all they did was set some package rules to avoid building the JSON component, and then removed the relevant source. By cloning the official repo, we can then combine the `debian/` folder from the source package, with modifications, and the upstream source in order to build the JSON libraries. Just "don't use it for evil"! 

First we create our "source" `tar` archive for the package build process (the name is explained below), then copy over, clean, and commit the stock `debian/` folder - I recommend doing this for all your custom packaging as it makes retracing your changes far easier!

```
$ tar -cvJf poco_1.7.6-lool.orig.tar.xz poco/
$ cp -a poco-1.7.6+dfsg1/debian poco/
$ cd poco/
$ git checkout -b debian
$ dh_clean
$ git add debian/
$ git commit -m "Initial debian folder from Stretch source package"
```
Now we can begin modifying the Debian package rules. This is fairly straightforward even without Debian packaging experience. I'll indicate the file edits with `vim <filename>`; you can replace the `vim` with the editor of you choice. The output that follows is a basic `git`-style diff of the changes, as generated as the changes are committed to the custom branch.

The first target is the `changelog` file, to tell it we have a new version. Note that the version string (`lool-1`) is chosen specifically because it is "higher" than the official package's `+dfsg1` string. You can validate this yourself using `dpkg --compare-versions`. This ensures that our custom packages will supersede the official ones, should you commit them to a custom repo and upgrade, though in this guide we install them locally with `dpkg`. Note that the formatting of this file must match exactly, including every space and the full date, but feel free to edit the note and name/email as you desire - this is irrelevant unless you intend to distribute the packages.

```
$ vim debian/changelog
@@ -1,3 +1,9 @@
+poco (1.7.6-lool-1) stable; urgency=medium
+
+  * A custom build of 1.7.6 including non-DFSG JSON libraries for LibreOffice Online
+
+ -- Your Name <you@example.com>  Tue, 06 Jul 2017 23:47:21 -0400
+
 poco (1.7.6+dfsg1-5) unstable; urgency=medium

   * Add missing dependencies (Closes: #861682)

```

The next file to edit is the `control` file. In here, we add an entry for the `libpocojson46` package that will also be built with `libpoco-dev`. This edit should not require any changes from what is presented here.

```
$ vim debian/control
@@ -228,3 +228,19 @@ Description: C++ Portable Components (POCO) Zip library
  consistent and easy to maintain.
  .
  This package provides the POCO Zip library.
+
+Package: libpocojson46
+Architecture: any
+Depends: libpocofoundation46 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Description: C++ Portable Components (POCO) JSON library
+ The POCO C++ Libraries are a collection of open source C++ class libraries
+ that simplify and accelerate the development of network-centric, portable
+ applications in C++. The libraries integrate perfectly with the C++ Standard
+ Library and fill many of the functional gaps left open by it.
+ .
+ POCO is built strictly using standard ANSI/ISO C++, including the standard
+ library. The contributors attempt to find a good balance between using advanced
+ C++ features and keeping the classes comprehensible and the code clean,
+ consistent and easy to maintain.
+ .
+ This package provides the POCO JSON library.
```

Next we edit the `rules` file to remove the exclusion of the JSON component.

```
$ vim debian/rules
@@ -4,7 +4,7 @@ DPKG_EXPORT_BUILDFLAGS = 1
 export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
 include /usr/share/dpkg/buildflags.mk

-CONFFLAGS = --prefix=/usr --no-samples --no-tests --unbundled --everything --omit=JSON --cflags="-DPOCO_UTIL_NO_JSONCONFIGURATION" --odbc-lib=/usr/lib/$(DEB_HOST_MULTIARCH)/
+CONFFLAGS = --prefix=/usr --no-samples --no-tests --unbundled --everything --odbc-lib=/usr/lib/$(DEB_HOST_MULTIARCH)/

 # Disable parallel build on armel and mipsel
 ifneq (,$(filter $(DEB_BUILD_ARCH),armel mipsel))
```

Now we remove the patches that disabled JSON support in the package. First we remove the patch, then we remove the `series` entry for it.

```
$ rm debian/patches/0006-Disable-JSON-targets-in-Makefiles.patch
$ vim debian/patches/series
@@ -6,7 +6,6 @@ no-link-dl-rt.patch  #could be removed now
 # patches for build/rules/*
 no-debug-build.patch
 no-strip-release-build.patch
-0006-Disable-JSON-targets-in-Makefiles.patch

 # upstream patches
 0007-Add-patch-for-OpenSSL-1.1.0.patch
```

Finally we remove the old lintian overrides (no longer needed) and create the `install` file for our new `libpocojson46` package.

```
$ rm debian/source.lintian-overrides
$ vim debian/libpocojson46.install
@@ -0,0 +1 @@
+usr/lib/libPocoJSON.so.*
```

We can now build the package; I use `-j4` on my quad-vCPU build machine but you should adjust this based on your core count for best performance. Note also that we're using `sudo` here; for whatever reason, trying to compile `libpoco` without root causes a spew of error messages like `object 'libfakeroot-sysv.so' from LD_PRELOAD cannot be preloaded`, on both my testing machines.


```
$ sudo dpkg-buildpackage -us -uc -j4
[lots of output]
dpkg-buildpackage: info: full upload (original source is included)
```

That last line indicates that the build succeeded; above it, we see a long list of generated packages in the parent directory. Move up a directory, remove the unneeded `dbgsym` packages, and install all the rest. Note the `sudo` commands again (due to the permissions of `dpkg-buildpackage`).

```
$ cd ..
$ sudo rm *-dbgsym_*.deb
$ sudo dpkg -i *.deb
```

We now have a working set of POCO libraries and can now begin building LibreOffice Online itself!

## Building LibreOffice Online

Once the dependencies are in place building the LibreOffice Online package itself is actually fairly straightforward - the repo contains a working `debian` folder, though it too requires some tweaking to build properly.

Begin by making a new directory, and cloning the git repo; I'm using version 2.1.2 as it's the latest stable one at the time of writing. Note that because the LibreOffice Online developers use tags, we have to actually `cd` into and `git checkout` the right version _before_ we proceed. Then, as we did for POCO, make a `tar` archive for the package build to use containing the source before we start editing anything.

```
$ mkdir ~/loolwsd
$ cd ~/loolwsd/
$ git clone https://github.com/LibreOffice/online.git
$ cd online/
$ git checkout -b debian tags/2.1.2
$ cd ..
$ tar -cvJf loolwsd_2.1.2.orig.tar.xz online/
$ cd online
```

We now need to do a some editing of the Debian control files, similar to POCO. First we add a `changelog` entry (as is customary).

```
$ vim debian/changelog
@@ -1,3 +1,9 @@
+loolwsd (2.1.2-7) stable; urgency=medium
+
+  * Custom build of 2.1.2 for Debian Stretch
+
+ -- Your Name <you@example.com>  Tue, 06 Jul 2017 23:47:21 -0400
+
 loolwsd (2.1.2-6) unstable; urgency=medium

   * see the git log: http://col.la/cool21
```

Next we edit the `control` file. By default, LibreOffice online depends on the `collaboraofficebasis5.3` suite, however we can override that and allow it to run against the stock Stretch `libreoffice` package. While the diff is long, simply search for the first instance of `collabora` on that line and delete everything after it, as well as the entry for `libssl1.0.0` which is obsolete in Stretch and should be present by default anyways.

```
$ vim debian/control
@@ -8,7 +8,7 @@ Standards-Version: 3.9.7
 Package: loolwsd
 Section: web
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, adduser, fontconfig, libsm6, libssl1.0.0, libodbc1, libxinerama1, libcairo2, libgl1-mesa-glx, libcups2, libdbus-glib-1-2, cpio, collaboraofficebasis5.3-calc (>= 5.3.10.15), collaboraofficebasis5.3-core (>= 5.3.10.15), collaboraofficebasis5.3-graphicfilter (>= 5.3.10.15), collaboraofficebasis5.3-images (>= 5.3.10.15), collaboraofficebasis5.3-impress (>= 5.3.10.15), collaboraofficebasis5.3-ooofonts (>= 5.3.10.15), collaboraofficebasis5.3-writer (>= 5.3.10.15), collaboraoffice5.3 (>= 5.3.10.15), collaboraoffice5.3-ure (>= 5.3.10.15), collaboraofficebasis5.3-en-us (>= 5.3.10.15), collaboraofficebasis5.3-en-us-calc (>= 5.3.10.15), collaboraofficebasis5.3-en-us-res (>= 5.3.10.15), collaboraofficebasis5.3-noto-fonts (>= 5.3.10.15), collaboraofficebasis5.3-draw (>= 5.3.10.15), collaboraofficebasis5.3-extension-pdf-import (>= 5.3.10.15)
+Depends: ${shlibs:Depends}, ${misc:Depends}, adduser, fontconfig, libsm6, libodbc1, libxinerama1, libcairo2, libgl1-mesa-glx, libcups2, libdbus-glib-1-2, cpio, libreoffice
 Description: LibreOffice Online WebSocket Daemon
  LOOLWSD is a daemon that talks to web browser clients and provides LibreOffice
  services.
```

Next we edit the `rules` to add a few missing things. First, we add some additional configuration flags for disabling SSL (instead use a forward proxy; this also prevents build errors) and specifying the library directory; this is needed for the build process to find the `libreoffice` libraries. We also add a call to `autogen.sh` in the configuration step (missing inexplicably in this version), as well as overrides to the auto-build (to allow `-jX` flags to work).

```
@@ -5,7 +5,7 @@ DPKG_EXPORT_BUILDFLAGS = 1
 
 include /usr/share/dpkg/default.mk
 
-CONFFLAGS = --enable-silent-rules --prefix=/usr --localstatedir=/var --sysconfdir=/etc --with-lokit-path=`pwd`/bundled/include $(CONFIG_OPTIONS)
+CONFFLAGS = --enable-silent-rules --disable-ssl --prefix=/usr --localstatedir=/var --sysconfdir=/etc --with-lokit-path=`pwd`/bundled/include --libdir=/usr/lib/x86_64-linux-gnu $(CONFIG_OPTIONS)
 
 # Avoid setcap when doing "make", when building for packaging
 # the setcap is done at installation time
@@ -16,10 +16,14 @@ export BUILDING_FROM_RPMBUILD=yes
        dh $@ --with=systemd
 
 override_dh_auto_configure:
+       ./autogen.sh
        ./configure $(CONFFLAGS)
 
 override_dh_auto_test:
        # do not test
 
+override_dh_auto_build:
+       dh_auto_build --parallel $(MAKEARGS)
+
 override_dh_installinit:
        # no init.d scripts here, assume systemd
```

Now we have to write some patches. `quilt` is a phenomenal tool for this, and I recommend reading up on it, but for simplicity I'll provide the patch files as-is. First create a `debian/patches` folder and create a `series` file in it.

```
$ mkdir debian/patches
$ vim debian/patches/series
@@ -0,0 +1,2 @@
+enable-ssl-always
+fix-libpath
```

Next we create the two patch files. The first is to enable SSL support always - this seems to contradict the above change to disable SSL, but otherwise the build process fails. The second fixes up the location of the `libreoffice` libraries so the `amd64`-only build can find where they exist in Stretch `amd64`.

_Note: to avoid showing a diff of a diff, the following two entries are the verbatim contents of the file_

```
$ vim debian/patches/enable-ssl-always
Description: Enable SSL always
 Ensure that SSL is always enabled during build
 .
 loolwsd (2.1.2-7) stable; urgency=medium
 .
   * Custom build of 2.1.2 for Debian Stretch
Author: Your Name <you@example.com>

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: https://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: 2017-06-23

--- loolwsd-2.1.2.orig/Makefile.am
+++ loolwsd-2.1.2/Makefile.am
@@ -38,9 +38,9 @@ endif

 AM_LDFLAGS = -pthread -Wl,-E,-rpath,/snap/loolwsd/current/usr/lib $(ZLIB_LIBS)

-if ENABLE_SSL
+#if ENABLE_SSL
 AM_LDFLAGS += -lssl -lcrypto
-endif
+#endif

 loolwsd_fuzzer_CPPFLAGS = -DKIT_IN_PROCESS=1 -DFUZZER=1 -DTDOC=\"$(abs_top_srcdir)/test/data\" $(AM_CPPFLAGS)

```
```
$ vim debian/patches/fix-libpath
Description: Fix the LibreOffice library path
 Ensure that the build can find the LibreOffice files
 .
 loolwsd (2.1.2-7) stable; urgency=medium
 .
   * Custom build of 2.1.2 for Debian Stretch
Author: Your Name <you@example.com>

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: https://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: 2017-06-23

--- loolwsd-2.1.2.orig/configure.ac
+++ loolwsd-2.1.2/configure.ac
@@ -166,7 +166,7 @@ AS_IF([test -n "$with_lokit_path"],
       [CPPFLAGS="$CPPFLAGS -I${with_lokit_path}"])
 lokit_msg="$with_lokit_path"

-LO_PATH="/usr/lib64/libreoffice"
+LO_PATH="/usr/lib/libreoffice"
 JAIL_PATH=not-set
 SYSTEMPLATE_PATH=not-set
 have_lo_path=false

```

One final tweak to perform is to edit the systemd unit file to point to the `libreoffice` templates directory rather than the Collabora one, and change the Red Hat-specific `EnvironmentFile` directive to the Debian one (which isn't installed by default but can be used if needed).

```
$ vim debian/loolwsd.service
@@ -3,8 +3,8 @@ Description=LibreOffice Online WebSocket Daemon
 After=network.target

 [Service]
-EnvironmentFile=-/etc/sysconfig/loolwsd
-ExecStart=/usr/bin/loolwsd --version --o:sys_template_path=/opt/lool/systemplate --o:lo_template_path=/opt/collaboraoffice5.3 --o:child_root_path=/opt/lool/child-roots --o:file_server_root_path=/usr/share/loolwsd
+EnvironmentFile=-/etc/default/loolwsd
+ExecStart=/usr/bin/loolwsd --version --o:sys_template_path=/opt/lool/systemplate --o:lo_template_path=/usr/lib/libreoffice --o:child_root_path=/opt/lool/child-roots --o:file_server_root_path=/usr/share/loolwsd
 User=lool
 KillMode=control-group
 Restart=always
```

Now we install some required `npm` dependencies; the `nodejs-legacy` package will provide our `npm`; don't install the `npm` package itself as this will cause dependency hell. I do this in the main homedir to avoid putting cruft into the source directories.

```
$ cd ~
$ npm install uglify-js exorcist d3 evol-colorpicker bootstrap eslint browserify-css d3
```

Finally, we can build the LibreOffice Online package.

```
$ cd ~/loolwsd/online/
$ sudo dpkg-buildpackage -us -uc -j4
[lots of output]
dpkg-buildpackage: info: full upload (original source is included)
$ cd ..
```

Install the resulting `deb` file and we're set - LibreOffice Online, in a Debian package. To install it on another machine, all we need are the packages generated by this guide (`libpoco-dev` and friends, and `loolwsd`).

### Bonus - Changing the LibreOffice Online directory

By default, the LibreOffice Online package installs the main components of the `loolwsd` service under `/opt/lool`. I'm not a fan of putting anything under `/opt` however, and in BLSE2 everything that is per-server and not automated via configuration management goes under `/srv`. If you also desire this, it's very straightforward to edit the Debian configuration to support installing to an arbitrary target directory before building the package.

```
$ cd ~/loolwsd/online/
$ vim debian/loolwsd.postinst.in
@@ -7,24 +7,24 @@ case "$1" in
        setcap cap_fowner,cap_mknod,cap_sys_chroot=ep /usr/bin/loolforkit || true
        setcap cap_sys_admin=ep /usr/bin/loolmount || true

-       adduser --quiet --system --group --home /opt/lool lool
+       adduser --quiet --system --group --home /srv/lool lool
        mkdir -p /var/cache/loolwsd && chown lool: /var/cache/loolwsd
        rm -rf /var/cache/loolwsd/*
        chown lool: /etc/loolwsd/loolwsd.xml
        chmod 640 /etc/loolwsd/loolwsd.xml

        # We assume that the LibreOffice to be used is built TDF-style
-       # and installs in @LO_PATH@, and that /opt/lool is
+       # and installs in @LO_PATH@, and that /srv/lool is
        # on the same file system

-       rm -rf /opt/lool
-       mkdir -p /opt/lool/child-roots
-       chown lool: /opt/lool
-       chown lool: /opt/lool/child-roots
+       rm -rf /srv/lool
+       mkdir -p /srv/lool/child-roots
+       chown lool: /srv/lool
+       chown lool: /srv/lool/child-roots

        fc-cache @LO_PATH@/share/fonts/truetype

-       su lool --shell=/bin/sh -c "loolwsd-systemplate-setup /opt/lool/systemplate @LO_PATH@ >/dev/null 2>&1"
+       su lool --shell=/bin/sh -c "loolwsd-systemplate-setup /srv/lool/systemplate @LO_PATH@ >/dev/null 2>&1"
        ;;

 esac
$ vim debian/loolwsd.service
@@ -4,7 +4,7 @@ After=network.target

 [Service]
 EnvironmentFile=-/etc/default/loolwsd
-ExecStart=/usr/bin/loolwsd --version --o:sys_template_path=/opt/lool/systemplate --o:lo_template_path=/usr/lib/libreoffice --o:child_root_path=/opt/lool/child-roots --o:file_server_root_path=/usr/share/loolwsd
+ExecStart=/usr/bin/loolwsd --version --o:sys_template_path=/srv/lool/systemplate --o:lo_template_path=/usr/lib/libreoffice --o:child_root_path=/srv/lool/child-roots --o:file_server_root_path=/usr/share/loolwsd
 User=lool
 KillMode=control-group
 Restart=always
```

---

I hope this helps you avoid many hours of headache! I'll document the configuration and integration of LibreOffice Online in another post. Happy building!
