Ansicht eines geöffneten Textdokuments aus Nextcloud in Collabora

Online-Office Collabora für Nextcloud mit Docker

In Nextcloud gibt es die Möglichkeit, mittels einer Online-Office-Applikation die gängigen Office-Dokumente für Textverarbeitung (docx, odt), Tabellenkalkulation (xlsx, ods) etc. zu editieren. Dort fungiert die Funktion als „Nextcloud Office“. Zwar gibt es für Nextcloud auch die App Collabora Online – Built-in CODE Server, die man direkt in Nextcloud installieren kann, allerdings ist davon aus Gründen der Performance und Stabilität eher abzuraten. Eine gute Alternative ist hier die Installation der Collabora Online Development Edition (CODE) als Docker-Container, der dann über einen Apache-Reverse-Proxy angesteuert wird.

In diesem Beitrag beschreibe ich die Installation und Konfiguration von CODE via Docker, die Einrichtung und Konfiguration eines Reverse-Proxy in Apache2 und natürlich die abschließende Konfiguration in Nextcloud.

Grundlage hier diese Anleitung ist Ubuntu 22.04 mit Apache 2.4.52, Docker 24.0.5 und Nextcloud 28.0.2. Man kann Collabora bei entsprechend vorhandenen Systemressoucen parallel zur bestehenden Nextcloud-Instanz auf dem selben Server oder auch auf einem dedizierten Server installieren.

CODE ist eine eingeschränkt nutzbare Version von Collabora. Es können nur zehn Personen gleichzeitig an Dokumenten arbeiten; 20 Personen können zeitgleich ein Dokument ansehen.

Installation und Konfiguration von Docker

Falls nicht schon geschehen, installierst Du zuerst Docker:

sudo apt install docker docker.io docker-compose-v2 -y

Um nicht jedes Mal mit sudo arbeiten zu müssen, fügst Du Dich noch selbst der docker-Gruppe hinzu und liest die Gruppenzugehörigkeit neu ein (sollten noch andere User auf dem System mit Docker arbeiten, ersetzt Du $USER einfach durch deren Benutzernamen):

sudo adduser $USER docker
newgrp docker

Jetzt richtet wir uns unsere Docker-Compose-Umgebung ein. Der Sinn von Docker-Compose ist, dass man einen oder mehrere Container anhand von Konfigurationsdateien (Docker-Compose-File) steuern („orchestrieren“) kann. Ich lege meine Docker-Compose-Files immer im Verzeichnis /usr/local ab. Zunächst legen wir das entsprechende Unterverzeichnis an und setzen die entsprechenden Zugriffsrechte (wenn mehrere Personen den Server administratieren, kannst du alternativ die Zugriffsrechte auch für eine gemeinsame Gruppe setzen):

sudo mkdir -p /usr/local/docker/collabora
sudo chown -R $USER:$USER /usr/local/docker

Docker-Compose-File erstellen & befüllen

Wir erstellen das Docker-Compose-File:

vi /usr/local/docker/collabora/docker-compose.yaml

In dieser Datei fügst Du dann folgenden Inhalt ein:

version: '3.8'

services:
  collabora:
    image: collabora/code:latest
    container_name: collabora
    ports:
      - '9980:9980'
    restart: always

Gehen wir kurz einige wichtige Zeilen durch:

  • Zeile 5: Hier wird festgelegt, welches Docker-Image verwendet werden soll.
  • Zeile 6: Hier wird der Container-Name definiert. Er muss einzigartig sein und darf kein weiteres Mal verwendet werden. Im Normalfall kann der Name collabora bleiben.
  • Zeile 8: Hier werden die Ports, auf die von außer- und innerhalb des Docker-Containers zugegriffen werden, definiert. Auch hier können diese im Normalfall so bleiben; ändern muss man sie lediglich, wenn man mehrere Collabora-Container auf dem gleichen System laufen lässt.

Jetzt starten wir aber erst einmal den Docker-Container:

docker compose -f /usr/local/docker/collabora/docker-compose.yaml up -d

Erst wird das Image des Docker-Containers geladen und dann wird der Container gestartet. Das dauert ein wenig und sieht dann in etwa so aus:

[+] Running 4/4
  collabora 3 layers [⣿⣿⣿]      0B/0B      Pulled
    31ad3619f756 Pull complete                                                                                                                                                                                                          
    abe7f4b212d5 Pull complete                                                                                                                                                                                                         
    739faa7189a4 Pull complete                                                                                                                                                                                                                                                                                                                                   
[+] Running 2/2
  Network collabora_default  Created                                                                                                                                                                                                    
  Container collabora        Started      

Collabora konfigurieren

Jetzt kopieren wir die Collabora-Konfiguration aus dem Docker-Container in das Verzeichnis, dem auch das Docker-Compose-File liegt:

docker cp collabora:/etc/coolwsd/coolwsd.xml /usr/local/docker/collabora/coolwsd.xml

In der coolwsd.xml passen wir nun alle notwendigen Einstellungen an:

vi /usr/local/docker/collabora/coolwsd.xml

Zunächst passen wir die Netzwerkeinstellungen an. Suche einfach nach diesem Abschnitt:

  • Hier passen wir den Wert im Tag proto an: aus dem default-Wert all wird IPv4.
  • Weiterhin fügst Du im Tag post_allow noch in einem host-Tag die IP-Adresse, der Nextcloud-Installation(en) ein, die auf die Collabora-Installation Zugriff haben sollen (die anderen, bereits gesetzten host-Tags bleiben unberührt). Wichtig ist hierbei, dass Du die IP-Adresse escapst. Sollte nur eine Nextcloud-Installation Zugriff haben sollen, fügst Du natürlich nur eine IP-Adresse hinzu.

Die Änderungen sind jeweils hervorgehoben:

<net desc="Network settings">
  <!-- On systems where localhost resolves to IPv6 [::1] address first, when net.proto is all and net.listen is loopback, coolwsd unexpectedly listens on [::1] only.
       You need to change net.proto to IPv4, if you want to use 127.0.0.1. -->
  <proto type="string" default="all" desc="Protocol to use IPv4, IPv6 or all for both">IPv4</proto>
  ...
  <post_allow desc="Allow/deny client IP address for POST(REST)." allow="true">
    ...
    <host>123\.123\.123\.123</host>
    <host>456\.456.\456\.465</host>
  </post_allow>
  ...
</net>

Danach passen wir die SSL-Konfiguration an:

  • Du setzt im Tag enable den Wert auf false.
  • Im Tag termination muss der Wert auf true gesetzt werden.

Die Zeilen mit Änderungen sind wieder hervorgehoben:

<ssl desc="SSL settings">
  <!-- switches from https:// + wss:// to http:// + ws:// -->
  <enable type="bool" desc="Controls whether SSL encryption between coolwsd and the network is enabled (do not disable for production deployment). If default is false, must first be compiled with SSL support to enable." default="true">false</enable>
  <!-- SSL off-load can be done in a proxy, if so disable SSL, and enable termination below in production -->
  <termination desc="Connection via proxy where coolwsd acts as working via https, but actually uses http." type="bool" default="true">true</termination>
  ...
</ssl>

Weiterhin müssen wir noch die Konfiguration für das Backend Storage anpassen: Mit der Konfiguration der alias_groups wird gesteuert, welche Nextcloud-Domains auf die Collabora-Installation Zugriff haben werden.

Per default ist die Einstellung so geregelt, dass diejenige Domain, die als erstes auf die Collabora-Installation zugreift, auch zukünftig immer nur darauf zugreifen kann. Das ist aber aus zwei Gründen problematisch:

  1. Bei einem Update oder einem Systemneustart „vergisst“ Collabora diese Einstellung.
  2. Es besteht auch die Möglichkeit, dass von mehreren Nextcloud-Domains oder -Installationen auf Collabora zugegriffen werden soll.

Daher empfiehlt sich in diesem Fall diese Einstellung zu setzen:

  • Setze zunächst für den Tag alias_groups das Attribut mode auf groups.
  • Weiterhin fügst Du einen neuen Tag group im alias_groups-Tag ein und setzt dort einen Tag host mit dem Attribut allow="true". In diesem host-Tag hinterlegst Du als Wert die Domain einschließlich Protokoll und Port der Nextcloud-Installation.

Die Zeilen, die ich der Konfiguration hinzugefügt bzw. bei denen ich etwas geändert habe, sind hervorgehoben:

<storage desc="Backend storage">
  ...
  <wopi desc="Allow/deny wopi storage." allow="true">
    ...
    <alias_groups desc="default mode is 'first' it allows only the first host when groups are not defined. set mode to 'groups' and define group to allow multiple host and its aliases" mode="groups">
    <!-- If you need to use multiple wopi hosts, please change the mode to "groups" and
            add the hosts below.  If one host is accessible under multiple ip addresses
            or names, add them as aliases. -->
      <group>
        <host allow="true">https://nextcloud.example.com:443</host>
      </group>
      <group>
        <host allow="true">https://nextcloud-2.example.com:443</host>
      </group>
    <!--<group>
            <host desc="hostname to allow or deny." allow="true">scheme://hostname:port</host>
            <alias desc="regex pattern of aliasname">scheme://aliasname1:port</alias>
            <alias desc="regex pattern of aliasname">scheme://aliasname2:port</alias>
            
    </group>-->
    <!-- More "group"s possible here -->
    </alias_groups>
  </wopi>
  ...
</storage>

Zuletzt setzen wir noch Benutzername (username) und Password (password). Später kannst Du über die URL https://collabora.example.com/browser/dist/admin/admin.html (Domain natürlich anpassen) mit dem Benutzernamen und dem Passwort auf die grafische Administrationsoberfläche im Browser zugreifen:

<admin_console desc="Web admin console settings.">
  ...
  <username desc="The username of the admin console. Ignored if PAM is enabled."></username>
  <password desc="The password of the admin console. Deprecated on most platforms. Instead, use PAM or coolconfig to set up a secure password."></password>
  ...
</admin_console>

Fertig? Dann speichern!

Anschließend setzen wir noch die korrekten Rechte:

chmod 644 /usr/local/docker/collabora/coolwsd.xml

Jetzt haben wir eine korrekte Collabora-Konfiguration in Form der coolwsd.xml und können sie nun über das Docker-Compose-File als eigenes Volume mounten:

vi /usr/local/docker/collabora/docker-compose.yaml

Hier fügst Du nach der letzten Zeile folgendes ein:

volumes:
  - ./coolwsd.xml:/etc/coolwsd/coolwsd.xml

Die Datei sieht dann so aus:

version: '3.8'

services:
  collabora:
    image: collabora/code:latest
    container_name: collabora
    ports:
      - '9980:9980'
    restart: always
    volumes:
      - ./coolwsd.xml:/etc/coolwsd/coolwsd.xml

Damit die neue Konfiguration greift, starten wir den Docker-Container abschließend neu:

docker compose -f /usr/local/docker/collabora/docker-compose.yaml up -d

Collabora-Container updaten

Um den Collabora-Container regelmäßig auf dem neusten Stand zu halten, legen wir einen Cronjob an, der einmal wöchentlich prüft, ob eine neue Version vorhanden ist, diese ggf. herunterlädt und den Container neustartet.

Zunächst legen wir einen Cronjob an:

sudo vi /etc/cron.d/collabora

Anschließend fügen wir folgende Zeile ein:

0 5 * * 7       root    docker pull collabora/code:latest && docker compose -f /usr/local/docker/collabora/docker-compose.yaml up -d 

So wird jeden Sonntag um 5:00 Uhr die Prüfung, ob ein Update vorhanden ist, durchgeführt.

Apache-Reverse-Proxy konfigurieren

Der Docker-Container, in dem Collabora läuft, ist bislang nur über den Port 9980 erreichbar. Damit er normal über den Port 443 (https) erreichbar ist, müssen wir noch den Reverse-Proxy konfigurieren. Dieser leitet die Anfragen dann von Port 443 an Port 9980 und schließlich an den Docker-Container weiter.

Falls der Apache-Server und Let’s Encrypt (zur Generierung des SSL-Zertifikats) noch nicht installiert sein sollte, dann geht das so:

sudo apt install apache2 certbot python3-certbot-apache -y

Danach müssen noch einige notwendige Module aktiviert werden:

sudo a2enmod headers proxy_connect proxy_http proxy_wstunnel rewrite 

Nun legen wir noch ein Verzeichnis und eine leere Datei im Apache-www-Verzeichnis an:

sudo mkdir /var/www/collabora
sudo touch /var/www/collabora/index.html
sudo chown -R www-data:www-data /var/www/collabora

Jetzt erstellen wir die Apache-Config-Datei, die später den Zugriff auf den Collabora-Container steuern wird:

sudo vi /etc/apache2/sites-available/collabora.conf

Hier fügst Du einfach folgende Konfiguration ein und passt sie entsprechend an:

<VirtualHost *:80>

        ServerName collabora.example.com
        DocumentRoot /var/www/collabora

        ErrorLog ${APACHE_LOG_DIR}/collabora.error.log
        CustomLog ${APACHE_LOG_DIR}/collabora.access.log combined

</VirtualHost>

Setze als ServerName die tatsächliche Domain ein, unter der Collabora erreicht werden soll ein, und passe ggf. auch den Dateinamen der Logs an.

Die Änderung speichern, dann den vHost aktivieren und anschließend den Apache neustarten:

sudo a2ensite collabora.conf
sudo systemctl restart apache2.service

Jetzt erzeugen wir noch ein SSL-Zertifikat, damit Collabora auch unter Port 443 erreichbar ist (bitte passe collabora.example.com durch Deine schon in der Apache-Config hinterlegen Domain an):

sudo certbot --apache -d collabora.example.com

Wenn Du das erste Mal auf dem Server mit Let’s Encrypt ein Zertifikat erzeugst, wirst Du auch nach Deiner Mail-Adresse gefragt und musst die Nutzungsbedingungen bestätigen. Außerdem wirst Du gefragt, ob Du einen Newsletter haben möchtest.

Wenn alles funktioniert hat, dann erscheint u.a. folgende Meldung:

Requesting a certificate for collabora.example.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/collabora.example.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/collabora.example.com/privkey.pem
This certificate expires on 2024-05-05.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Deploying certificate
Successfully deployed certificate for collabora.example.com to /etc/apache2/sites-available/collabora-le-ssl.conf
Congratulations! You have successfully enabled HTTPS on https://collabora.example.com

Das Zertifikat ist dann drei Monate gültig.

Wichtiger aber ist der Hinweis, dass ein neuer vHost unter dem Pfad /etc/apache2/sites-available/collabora-le-ssl.conf erzeugt worden ist.

Schauen wir uns diese Datei einmal an:

sudo vi /etc/apache2/sites-available/collabora-le-ssl.conf

Der Inhalte sollte in etwa so aussehen (ggf. sind die letzten drei Zeilen vor dem schließenden </VirtualHost>-Tag nicht eingerückt – aus ästhetischen Gründen habe ich das an dieser Stelle nachgeholt):

<IfModule mod_ssl.c>
<VirtualHost *:443>

        ServerName collabora.example.com
        DocumentRoot /var/www/collabora

        ErrorLog ${APACHE_LOG_DIR}/collabora.error.log
        CustomLog ${APACHE_LOG_DIR}/collabora.access.log combined


        SSLCertificateFile /etc/letsencrypt/live/collabora.example.com/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/collabora.example.com/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

Jetzt muss noch nach der SSL-Konfiguration und vor dem schließenden </VirtualHost>-Tag die Proxy-Einstellungen eingefügt werden, die dafür sorgen, dass die Anfrage an den Container weitergeleitet werden (auch hier in der Collabora-Doku nachlesbar):

########################################
# Reverse proxy for Collabora Online   #
########################################

AllowEncodedSlashes NoDecode
ProxyPreserveHost On

# static html, js, images, etc. served from coolwsd
# 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

# 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

Die Datei sollte dann so aussehen:

<IfModule mod_ssl.c>
<VirtualHost *:443>

        ServerName collabora.example.com
        DocumentRoot /var/www/collabora

        ErrorLog ${APACHE_LOG_DIR}/collabora.error.log
        CustomLog ${APACHE_LOG_DIR}/collabora.access.log combined


        SSLCertificateFile /etc/letsencrypt/live/collabora.example.com/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/collabora.example.com/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf


        ########################################
        # Reverse proxy for Collabora Online   #
        ########################################

        AllowEncodedSlashes NoDecode
        ProxyPreserveHost On

        # static html, js, images, etc. served from coolwsd
        # 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

        # 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

</VirtualHost>
</IfModule>

Diese speichern und einmal den Apache neuladen:

sudo systemctl reload apache2.service

Der Collabora-Server ist nun fertig konfiguriert.

Nextcloud konfigurieren

Jetzt muss noch Nextcloud die entsprechende Konfiguration setzt werden.

Das kannst Du in Deiner Nextcloud-Installation unter Verwaltungseinstellungen -> Office vornehmen. Wähle nun „Verwende deinen eigenen Server“ aus und gibt in das Feld „URL (und Port) des Collabora Online-Servers“ die oben hinterlegte Domain ein: collabora.example.com

Konfiguration von Collabora in Nextcloud

Nach dem Speichern erhält man eine Erfolgsmeldung.

Allerdings erscheint auch folgende Meldung:

Du hast die Erlaubnisliste für WOPI-Anforderungen nicht konfiguriert. Ohne diese Einstellung können Benutzer über WOPI-Anfragen Dateien herunterladen, auf die sie möglicherweise keine Zugriffsrechte haben. Für weitere Informationen hier klicken

Du musst hier einfach noch die IP Deines Collabora-Server hinterlegen. Da das gegenwärtig im Nextcloud-Frontend nicht funktioniert, kannst Du das einfach in der Bash auf Deinem Nextcloud-Server hinterlegen:

sudo -u www-data php /var/www/nextcloud/occ config:app:set richdocuments wopi_allowlist --value='321.321.321.321'

Wenn Du nun ein neues Textdokument anlegst, siehst das so aus:

Ansicht von Collabora in Nextcloud

Und jetzt kannst Du mit Collabora arbeiten.

Sollte irgendetwas nicht funktionieren oder noch etwas unklar sein, freue ich mich über Deinen Kommentar.

4 Kommentare

  1. Hallo Erik,
    danke für den Artikel.
    Ich habe es, bis zur Lets Encrypt, Lokal eingerichtet. Da ich dieses nur im Heumnetzwerk nutze wäre es super wenn es eine Anleitung dazu gäbe.
    Der Collabora Server meldet bei aufruf OK und in der Nextcloud wird der Server auch verbunden.
    Wenn ich alleridngs ein neues Dokument erstelle oder bearbeiten will bekomme ich folgende Fehlermeldung
    „Fehler beim Lesen des Dokuments aus dem Speicher, bitte versuchen Sie, das Dokument erneut zu laden.
    Please check the Collabora Online server log for more details and make sure that Nextcloud can be reached from there.“
    und im Log in Portainer sagt er mir:
    „wsd-00001-00033 2024-04-20 00:48:35.491125 +0000 [ websrv_poll ] ERR #19: Error while handling poll at 0 in websrv_poll: #19 (handshake): unknown. BIO error: 167773206, rc: -1: error:0A000416:SSL routines::sslv3 alert certificate unknown:
    C0D67DFA097F0000:error:0A000416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown:ssl/record/rec_layer_s3.c:1590:SSL alert number 46
    | net/Socket.cpp:491“

    Ich bin leider der absolut N00B in solchen Dingen.
    Meinst du, du könntest mit weiter helfen?

    Grüße
    Michael

    1. Hallo Michael,
      lokal hab ichs noch nicht probiert, aber evtl. könnte Dir hier mkcert weiterhelfen?
      Ich schau mir das bei Gelegenheit mal genauer an, aber das wird nichts vor Sommer 😉

      Viele Grüße,
      Erik

  2. Hallo,

    da ich mein Nextcloud via NextcloudPi laufen lasse und Collabora als Docker auf dem gleichen Host packen wollte, lief es bei mir nicht ganz so rund, wie mit zwei verschiedenen Hosts, wie hier im Beispiel verwendet: die Nextcloud-Instanz meldete ständig im Collabora log (`docker compose logs collabora`)

    „`
    WOPI::CheckFileInfo failed for URI [https:///index.php/apps/richdocuments/wopi/files/820376_oci20ix30ygu?access_token=FuguwmyP9Q4LEKSkLxdazmQUGUXOTc3d&access_token_ttl=0]: 403 (Forbidden) Forbidden
    „`

    Die Lösung war dann die wopi_allowlist variable in der Nextcloud-Config einfach leer zu lassen. Bin zu sehr ein Nextcloud-Noob (darum auch NextcloudPi) um die Sicherheitsimplikationen abzuschätzen, aber alles andere (globale IP-Adresse der Nextcloud-Instanz, NAT-IP-Adresse der Nextcloud-Instanz, IP-Adresse des Docker-Interfaces auf dem Host, …) hatte nur zu dem obigen Ergebnis geführt.

    Vielleichts hilfts ja anderen, die diesen ansonsten sehr hilfreichen Blogartikel lesen.

    Viele Grüße
    miri64

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert