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.
Inhalt
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-Wertall
wirdIPv4
. - Weiterhin fügst Du im Tag
post_allow
noch in einemhost
-Tag die IP-Adresse, der Nextcloud-Installation(en) ein, die auf die Collabora-Installation Zugriff haben sollen (die anderen, bereits gesetztenhost
-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 auffalse
. - Im Tag
termination
muss der Wert auftrue
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:
- Bei einem Update oder einem Systemneustart „vergisst“ Collabora diese Einstellung.
- 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 Attributmode
aufgroups
. - Weiterhin fügst Du einen neuen Tag
group
imalias_groups
-Tag ein und setzt dort einen Taghost
mit dem Attributallow="true"
. In diesemhost
-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
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:
Und jetzt kannst Du mit Collabora arbeiten.
Sollte irgendetwas nicht funktionieren oder noch etwas unklar sein, freue ich mich über Deinen Kommentar.
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
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
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
Danke für den Hinweis! Lokal habe ichs in der Tat auch noch nicht ausprobiert.