Slackware Cloud Server Series Episode 5: Collaborative Document Editing

Hi all!
A spin-off from our previous Episode in this series is this fifth article about using Slackware as your private/personal ‘cloud server’.
Check out the list below which shows past, present and future episodes in the series, if the article has already been written you’ll be able to click on the subject.
The first episode also contains an introduction with some more detail about what you can expect.
These articles are living documents, i.e. based on readers’ feedback I may add, update or modify their content.

Collaborative document editing

In the previous Episode called “Productivity Platform” I have shown you how to setup the NextCloud platform on your Slackware server. I had promised a separate article about the addition of “collaborative editing” and this is it.

Collaborative editing on documents allows people from all over the world to have the exact same document (text, spreadsheet, presentation, vector graphics) open in a web-based online editor and collaborate on its content in real-time. Every editor can see what the others are currently working on.
The most widely used online office suite with these capabilities is Microsoft Office 365.

Of course, Microsoft 365 is not free. It uses a license model where you pay for its use per month. If you stop paying… you lose access to your online office suite and if you are unlucky, you lose access to your OneDrive files as well.

How is the situation in the Open Source world? Looking for free and open (source as well as standards-adhering!) desktop office programs, many people acknowledge that Libreoffice is an important OSOSS (Open Standards & Open Source Software) alternative to Microsoft’s Office line of programs. However… a cloud-native online web-based variant of the LibreOffice suite of programs is not trivially accessible. By nature, online software needs to be hosted somewhere and by extension, the documents you edit online need to be maintained on cloud storage as well… a challenge for free software enthusiasts when the truth is that hosting costs money. The commercially successful Microsoft Office 365 has the dominant position there.

Now, this article is going to free you (a bit) from Big Tech. I will show you how to enrich your personal Slackware Cloud Server with exactly that what seems unattainable for free software lovers: a web-based online version of LibreOffice which makes it possible for you and yours to (jointly if you want) edit the documents that you are already hosting in your NextCloud accounts.

This will be achieved by using the power of LibreOffice. An web-based version of LibreOffice exists and is called Collabora Online. It is being developed by Collabora Productivity, a subsidiary of the company Collabora who are a main contributor of LibreOffice code for many years already, and have a commercial partnership with The Document Foundation.
Formerly known under the name of LibreOffice Online, Collabora have moved the project development from LIbreOffice’s git repository to their own git repository and renamed it.
The Collabora Online Development Edition (CODE) is the version offered for free to the Open Source community (similar to the LibreOffice Community Edition) but Collabora also offer a commercial paid-for version of their Online suite. Companies using the commercial variant basically sponsor Collabora for the development of the Open Source version.

This article focuses on the integration of CODE into your NextCloud environment.

Preamble

For the sake of this article, I am using an ‘artificial’ non-existing domain name “darkstar.lan”.
I expect that your own real-life Slackware server is running Nextcloud at a publicly accessible URL, but in this article it will be:

  • https://darkstar.lan/nextcloud/

The Collabora Online Development Edition will run at its own hostname in the “darkstar.lan” domain. It is of course a virtual server running in Apache httpd, and you probably defined it in a “<VirtualHost></VirtualHost>” block. This article assumes that we are going to host CODE on a bare webserver which is already running at:

  • https://code.darkstar.lan/

Collabora Online Development Edition (CODE)

CODE is not a standalone application. It is a document-editor backend service without user interface and it communicates with your NextCloud platform via WOPI (the ‘Web Application Open Platform Interface’ protocol). It expects NextCloud to provide the user interface (a web page).
CODE is a ‘WOPI Client‘ with an API that offers editing capabilities for the documents that you host on your NextCloud (the ‘WOPI Host‘). The online editor is displayed in an embedded HTML frame right inside your familiar NextCloud environment.

The steps that we are going to take in order to integrate CODE into Nextcloud are:

  • Get a Docker container running with CODE inside and listening at 127.0.0.1:9980 for connection requests.
  • Configure Apache httpd with a reverse proxy so that this localhost port is hidden behind an externally accessible secure URL:  https://code.darkstar.lan .
  • Add the ‘richdocuments‘ app to your NextCloud server and connect it to our CODE container.
  • Tell your users!

First step: download the Collabora Online Docker image. The ‘docker run‘ command which we are going to execute in a moment would also perform that download if necessary, but it does not hurt to already make the image available locally ahead of time, so that any startup issues of the container are not clouded by connectivity issues toward the Docker Hub:

# docker pull collabora/code

The ‘docker run‘ commandline which starts the CODE container is a complex one, so let’s briefly look at its most important parameters.
As stated in the ‘preamble’, our Collabora Online Development Edition will run at hostname “code.darkstar.net” and you need to tell it explicitly which other hosts are permitted to embed it in a web-page. For us this means that our NextCloud server must be allowed to embed content originating from the CODE container when you open a document for editing. Our NextCloud hostname is passed to the container with the “domain” parameter. Make sure to escape all dots in the hostname with double backslashes (\\), since this string will be evaluated as a regular  expression (and bash ‘eats’ the first backslash).
In case you want to permit the use of your CODE Docker container to more than one Nextcloud server (for instance, you want to allow your friend who is also running a NextCloud server to use your CODE server as its collaborative editor)? Then add more hostnames to the ‘domain‘ parameter like this:

'domain=code\\.darkstar\\.lan\|second\\.nextcloud\\.com'

Multiple Nextcloud hosts need to be separated by backslash and pipe: “\|“.

The command to start the container is as follows:

# docker run -t -d -p 127.0.0.1:9980:9980 \
  -e 'domain=darkstar\\.lan/nextcloud' \
  -e "server_name=code.darkstar.lan" \
  -e "username=codeadmin" -e "password=My_Secret_Pwd" \
  -e "DONT_GEN_SSL_CERT" \
  -e "extra_params=--o:ssl.enable=false --o:ssl.termination=true --o:net.proto=IPv4 --o:net.post_allow.host[0]=.+ --o:storage.wopi.host[0]=.+" \
  --restart always --cap-add MKNOD collabora/code

Optionally, run with additional dictionaries.

-e 'dictionaries=nl de en fr es ..'

Through the “-p” parameter we expose the CODE container’s address at 127.0.0.1:9980 .

You see several parameters (-e "DONT_GEN_SSL_CERT" -e "extra_params=--o:ssl.enable=false --o:ssl.termination=true") that are meant to disable the container’s use of SSL encryption when communicating with the outside world. The Apache reverse proxy which we will place in front of it takes care of client-to-server encryption using a Let’s Encrypt certificate instead of the container’s self-signed certificate.

There are also a couple of parameters (-e "extra_params= --o:net.proto=IPv4 --o:net.post_allow.host[0]=.+ --o:storage.wopi.host[0]=.+") which allow the Collabora Online server to be used by hosts in your network – like your NextCloud instance. Note the use of wildcard “.+” in both the “net.post_allow.host” and “storage.wopi.host” options. I have been unsuccessful in determining a more restricted wildcard that is a better match with my network IP ranges. In the end I went for what I could find in online help forums as something which works.

The “MKNOD” capability is needed for CODE to do its work, apparently it needs to be able to create special device nodes in the filesystem using the ‘mknod‘ command. Note that according to the documentation, this makes the CODE image incompatible with Docker Swarm, but Swarm is not within the scope of my article series anyway.

If your ‘docker run‘ command-line contains a “username” and “password” parameter, then Collabora Online will enable its admin console (only accessible with the above username/password) at: https://code.darkstar.lan/browser/dist/admin/admin.html . At that URL you will find some statistics of the operations performed by the online editor.

Configuring Apache

Note that in many places on the Internet, the documentation for the reverse proxy still mentions the old LibreOffice OnLine “lool” and “loolwsd” phrases instead of using the new COllabora OnLine phrases “cool” and “coolwsd“. Luckily, Collabora’s own documentation is correct: https://sdk.collaboraonline.com/docs/installation/Proxy_settings.html. So here is what I am using on my CODE server, running on IP address:port “127.0.0.1:9980” and reverse-proxied to https://code.darkstar.lan/ .
I assume you know where to add it to your Apache httpd VirtualHost definition:

# START Reverse proxy to the CODE Docker container:
#
AllowEncodedSlashes NoDecode
ProxyPreserveHost On
ProxyTimeout 900

# Cert is issued for code.darkstar.lan and we proxy to localhost:
SSLProxyEngine On
RequestHeader set X-Forwarded-Proto "https"

# Static html, js, images, etc. served from coolwsd;
# And 'browser' is the client part of Collabora Online:
ProxyPass /browser http://127.0.0.1:9980/browser retry=0
ProxyPassReverse /browser http://127.0.0.1:9980/browser

# WOPI discovery URL:
ProxyPass /hosting/discovery http://127.0.0.1:9980/hosting/discovery retry=0
ProxyPassReverse /hosting/discovery http://127.0.0.1:9980/hosting/discovery

# Capabilities:
ProxyPass /hosting/capabilities http://127.0.0.1:9980/hosting/capabilities retry=0
ProxyPassReverse /hosting/capabilities http://127.0.0.1:9980/hosting/capabilities

# Do not forget WebSocket proxy:
RewriteEngine on
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]

# Main websocket
ProxyPassMatch "/cool/(.*)/ws$" ws://127.0.0.1:9980/cool/$1/ws nocanon

# Admin Console websocket:
ProxyPass /cool/adminws ws://127.0.0.1:9980/cool/adminws

# Download as, Fullscreen presentation and Image upload operations:
ProxyPass /cool http://127.0.0.1:9980/cool
ProxyPassReverse /cool http://127.0.0.1:9980/cool
# Compatibility with integrations that use the /lool/convert-to endpoint:
ProxyPass /lool http://127.0.0.1:9980/cool
ProxyPassReverse /lool http://127.0.0.1:9980/cool
#
# END Reverse proxy to the CODE Docker container

Upgrading the Docker image for CODE

Occasionally, new versions of this docker image are released with security and feature updates. This is how you upgrade to a new version:

Grab the new docker image:

$ docker pull collabora/code

List docker images:

$ docker ps

From the output you can glean the Container ID of your CODE docker container. Stop and remove the Collabora Online docker container:

$ docker stop CONTAINER_ID
$ docker rm CONTAINER_ID

Remove the old un-used image, after looking up its ID (check the timestamp):

$ docker images | grep collabora
$ docker image rm IMAGE_ID

Start a container based on the new image, using the same ‘docker run -d‘ command as before.

CODE Docker container configuration

The default configuration for the CODE Docker image is contained in a file inside the container, called “/etc/coolwsd/coolwsd.xml” . Some of the configuration options are documented online, but the file itself is well-documented too.

After starting the container, you can copy the configuration file out of the container using docker commands as shown below. After making your changes you copy it back into the container using docker commands. When a configuration change is detected by the running container it will restart (this is why it is important to have “--restart always” as part of your ‘docker run‘ commandline).
How to do this:

Determine the CODE Docker ID by looking at the running containers:

$ docker ps | grep code

With an output like this:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e3668a79b647 collabora/code "/start-collabora-onâ?¦?" 2 weeks ago Up 7 days 127.0.0.1:9980->9980/tcp suspicious_kirch

Copy out the “coolwsd.xml” configuration file into the current directory of your host filesystem:

$ docker cp e3668a79b647:/etc/coolwsd/coolwsd.xml coolwsd.xml

Make your configuration changes to the local copy and then add it back into the container:

$ docker cp coolwsd.xml e3668a79b647:/etc/coolwsd/coolwsd.xml

The CODE container needs some time for its automatic restart, so wait a bit before you try to access it again from inside NextCloud.

Custom Docker Image

The Docker image for CODE can be customized within limits, using the variables in its configuration file, see above. But if you need substantial customization like adding more fonts or removing the 20-concurrent-open-documents limit, you can rebuild the Docker image yourself.
The code to rebuild the image can be found in the Collabora Online github repository. Use the available scripts like “install-collabora-online-ubuntu.sh” to create a custom script for your Slackware server, add your desired customizations like additional fonts or packages to that script and build your own custom Docker image with it.
Of course, the command-line to start your CODE container must be adapted to use your custom image… since you no longer want the default image to be pulled from the “collabora/code” repository in the Docker Hub.

Adding CODE to NextCloud

The preliminaries have been dealt with. Now we are getting to the core of the story: connecting your NextCloud server to the online editor backend.

The ‘richdocuments‘ app is the glue we need on NextCloud to offer collaborative document editing capabilities to our users. The human-readable name of this app as listed in your app overview is “NextCloud Office”. In fact there is an extended version of the app called ‘richdocumentscode‘ which contains an embedded version of CODE, but it is severely under-performing. I enabled the embedded CODE server in that app only to find that it crippled my complete NextCloud platform. Every action slowed down to a horrible crawl. That was the moment I decided I needed CODE to run separately, in a Docker container and outside of NextCloud.

Get the ‘richdocuments’ app by going to “Profile > Apps” and search for it in the appstore. Install it and then go to the new menu item which has suddenly appeared: “Profile > System > Administration > Collabora Online Development Server” so you can configure the URL of your Collabora Online container:

The configuration boils down to:

  • Select the radio-button ‘Use your own server‘;
  • Enter the URL “https://code.darkstar.lan/“;
  • Save

NextCloud will make an attempt to contact your CODE server and if it gets the correct responses back, the configuration page will display a green checkbox along “Collabora Online server is reachable“.

All done! We can now check out how this online office suite looks on our NextCloud.
If you are more a ‘television personality’, you can also watch a video about how to add CODE to NextCloud, created by NextCloud’s own Marketing Director (and former member of the KDE marketing team) Jos Poortvliet:

 

Using CODE in NextCloud

Once CODE is available in your NextCloud and you click on a document, you see the connection to the online editor being initialized:

This process takes a few seconds and you end up in a web-based editor which looks like:

There it is. An online web-based office suite based on LibreOffice, which is able to open and edit the documents you are storing in your NextCloud account. And if you tell NextCloud to share your document(s) with others, then they too can collaborate on your document, all together in real-time.

Thanks

You made it! After reading and implementing the ideas from these first five articles in the Series you should now have a Slackware Cloud Server up and running, full of features that everybody will be envious of, and it’s all free and under your control! No more need for Google, Microsoft, Amazon, Zoom, Dropbox and the likes. Meet and collaborate to your hearts’ desire with family, friends, co-workers or groups of Open Source developers.

Good luck and let me know about your successes, but also your frustrations and how you overcame your knowledge gaps (these articles assumed quite a bit of prior knowledge of running a webserver, configuring an online domain, managing your firewall etcetera).

There’s some episodes remaining, doing a deep-dive into Etherpad and setting the first steps into creating your own private Docker Hub without artificial usage limitations. Writing those last two episodes will take more time, so do not expect them to be released in the next couple of weeks; however I hope you will like those as well.

Eric

8 thoughts on “Slackware Cloud Server Series Episode 5: Collaborative Document Editing

  1. Hi Eric,

    Slackware Cloud Server Series are a monumental contribution to Slackware in terms of clarification for it’s usage in a a sophisticated environment. I want to thank you for your effort, but above all, for your generosity in sharing your vast knowledge.

    I confess that little by little I am assimilating and digesting each article, because in several cases I have to investigate and understand concepts that are a contribution and a precondition for various steps in the article. I feel I have learned and understood a lot in my Slackware learning curve.

    Thank you very much Eric, behind this series of articles there is a big effort in terms of research and sharing that knowledge in a clear way.

    I will share with you how I am progressing.

    Thanks again, Eric.


    1. Hi Francisco,
      I hope you learn a lot from this article series, and indeed I will be very interested to hear about your (and other’s) adventures. I hope that in turn, I myself will be able to learn something from the feedback to the various episodes.
      Good luck!


  2. Pingback: Links 14/2/2022: MariaDB 10.7, KDE Frameworks 5.91.0, and Linux 5.17 RC4 | Techrights

  3. Hi Eric,

    Thanks so much for this great series of articles, it seems like you might have spent quite a bit of time on this project :-).
    I’m interested in trying out some or all of these ideas, but I’m a bit concerned that my little server might not cope with it all. Can you give some indication of the resources needed to run all these docker containers and apps (assuming a minimal number of users)? Will my raspberry pi grind to a halt?

    Cheers,
    Trevor


    1. A raspberry pi? Most probably it will buckle under load. But you can still use it to test whether it works.
      After all, it’s not much more than a dockerd process, a redis process, and a lot of httpd threads. They don’t eat large amounts of RAM or CPU.
      If you want to offer ‘cloud services’ to people around you, disk space and disk writes are more relevant, and the SD card of a Pi is not going to survive long.



  4. Eric, I can finally edit my documents inside my nextcloud. Thank you!

    The ‘-e domain=cloud\\.mydomain’ \ was rejected with the following error. I suppose that something changed in the latest image
    #-e ERR: Use of domain variable is not supported. First host/domain who tries to connect to COOL is always allowed.
    #To allow multiple host and its aliases use something like this and pass it as env variable:
    #aliasgroup1=https://domain1:443,https://its-alias|its-second-alias:443


    1. Indeed, the documentation page https://sdk.collaboraonline.com/docs/installation/CODE_Docker_image.html mentions the difference in parameter invocation, the change happened between versions 21.11.2.4.1 and 21.11.3.6 of the CODE Docker image.
      I think that means that my original example line:
      -e 'domain=code\\.darkstar\\.lan\|second\\.nextcloud\\.com'
      needs to be split into:
      -e 'aliasgroup1=https://code.darkstar.lan' -e 'aliasgroup2=https://second.nextcloud.com'


Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.