Working Configuration for Apache with Collabora Docker

I know this is unusual – but I actually wanted to post a working configuration for using the Collabora Docker image. I’m NOT running Collabora Code or the combination product that contains the docker image of Nextcloud/Collabora together. This is a straight Collabora Docker installation

My setup (which may be different than yours).

First I’ve virtualized my entire setup running within FreeNAS.

  1. Nextcloud is installed within a freebsd jail (I used these instructions: https://www.samueldowling.com/2018/12/08/install-nextcloud-on-freenas-iocage-jail-with-hardened-security/). Nextcloud is located on a different machine than collabora.

  2. Collabora is installed within an Ubuntu 18.04 VM within FreeNAS. I’m using the Collabora Docker image and not the server installation.

  3. I unfortunately have two Reverse Proxies in my setup (I suppose many of you may have one – this complicated setup unfortunately was needed because I can’t run Docker containers within freebsd (or at least it doesn’t work well))

Bad Schematic of my setup:

Internet —> pfSense Router --> Apache Reverse Proxy (FreeBSD) --> Apache Reverse Proxy(Ubnt)

Nextcloud runs as virtual host on FreeBSD Apache
Collabora/Docker runs on the Apache Reverse Proxy (Ubnt)

I’m using SSL certs from Let’s Encrypt. Both the the Apache Reverse Proxy (FreeBSD) and Apache Reverse Proxy (Ubnt) have a Fully Qualified Domain Name (FDQN) that is contained within the Lets Encrypt SSL certificate. The FQDN’s are necessary for SSL to function – but it also complicates things since when setting up things you need to refer to each individual server by FQDN and not by IP address. So specifically on my cert I have
nextcloud.domain.com (this will be used for the NextCloud Virtual Host – as named in apache)
office.domain.com (this is used for the Apache Reverse Proxy Virtual Host that then proxies unencryped requests towards Collabora/Collabora Docker)
— Collabora/Docker in this scenario doesn’t have a FQDN – its just known as 127.0.0.1:9980. I don’t believe you need fully qualified domain names when running things over simple http.
---- (Other domains are contained within the certificate which describe other Virtual Hosts running within the Apache FreeBSD installation).

I’m also using Cloudflare as my DNS provider (highly recommend – its free and totally gives you control of your Domain Names). In my instance nextcloud.domain.com and office.domain.com either have to have an “A” or “CNAME” entry registered. Nextcloud.domain.com is associated with my WAN IP. Physically the connection is routed from the internet to my ip address through my router (which port forwards 80/443) to the Apache Web Server/Reverse Proxy.

Some trickery needs to be employed for the office.domain.com name to function correctly. Although at Cloudflare office.domain.com is associated with my WAN IP address, this unfortunately isn’t correct (by default all domain names at cloudflare need to associated with an IP address). My pfsense router also acts as my DNS server for my LAN. Local computers on the LAN will first consult their /etc/hosts file, then query the router, and then finally the domain name servers in order to associate a specific domain name with an IP address. I added an entry within my pfSense router that associates office.domain.com with an internal IP address (specifically in my case 10.0.1.62). If you aren’t able to do this step, it would also be possible to change the /etc/hosts file on the first proxy server (Apache on Free BSD) that would have an entry like:
10.0.1.62 office.domain.com

Unfortunately all this trickery and elaborate setup is needed to allow SSL to work appropriately. In this scenario traffic from the Internet is encrypted to the Apache FreeBSD reverse proxy, which then decrypts/re-encrypts via SSLProxy to the Apache UBNT reverse proxy. I’ll post a link later on the specifics on how this is done with Let’s Encrypt Certificates since this took me a while to actually get it working – with a lot of reading and posts to the Let’s Encrypt Forums (https://community.letsencrypt.org/t/can-i-use-le-certs-for-intranet-server/103317).

Because of my setup whereby the Collabora/Docker instance is running on the second reverse proxy, I felt I didn’t need to encrypt traffic between the reverse proxy and the Docker image. (YOUR SETUP MAY BE DIFFERENT THAN THIS SINCE THIS WILL EFFECT SOME OF THE SETTINGS OF COLLABORA DOCKER).

So now finally to discuss the specifics with the Collarbora Setup

  1. Nextcloud Instance – Download and install app within Nextcloud known as Collabora Online. Here is website Only for Reference (https://www.collaboraoffice.com/collabora-online/)

Within Settings for the Collabora OnLine - I put my domain as https://office.domain.com and Left Unchecked Disable Certificate Verification. This was left unchecked since Nextcloud is communicating through Collabora through the Reverse Proxy. I am letting the Reverse
e Proxy handle the SSL implementation and not Nextcloud/Collabora. (THIS MAY BE DIFFERENT FOR YOU).

  1. Configuration of the Reverse Proxy. I’m posting here my Virtual Host Apache File for the Reverse Proxy that Runs on same machine as Collabora/Docker.
<VirtualHost *:80>
    ServerName office.domain.com
    Redirect permanent / https://office.domain.com
</VirtualHost>

<VirtualHost *:443>
  ServerName office.domain.com
  DocumentRoot "/var/www/office.domain.com/html"
  DirectoryIndex index.html index.htm /index.php index.php
  ErrorLog ${APACHE_LOG_DIR}/office.domain.com-error.log
  CustomLog ${APACHE_LOG_DIR}/office.domain.com-access.log combined

  SSLEngine On
  SSLCertificateFile /etc/letsencrypt/live/domain.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/domain.com/privkey.pem
  ##Include /etc/letsencrypt/options-ssl-apache.conf

  SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
  SSLCipherSuite          ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY130
5:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDH
E-RSA-AES128-SHA256
  SSLHonorCipherOrder     on
  SSLCompression          off
  SSLSessionTickets       off
  SSLOptions              +StrictRequire

  <IfModule mod_headers.c>
         # HSTS (mod_headers is required) (15768000 seconds = 6 months)
         Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
   </IfModule>

  # Encoded slashes need to be allowed
  AllowEncodedSlashes NoDecode

  # Container uses a unique non-signed certificate
  # These four settings here are only needed if attempting to establish an SSL connection between reverse proxy and the Collabora/Docker container
  #SSLProxyEngine On
  #SSLProxyVerify None
  #SSLProxyCheckPeerCN Off
  #SSLProxyCheckPeerName Off

  # keep the host
  ProxyPreserveHost On

  # static html, js, images, etc. served from loolwsd
  # loleaflet is the client part of LibreOffice Online
  ProxyPass /loleaflet http://127.0.0.1:9980/loleaflet retry=0
  ProxyPassReverse /loleaflet http://127.0.0.1:9980/loleaflet

  # 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 "/lool/(.*)/ws$" ws://127.0.0.1:9980/lool/$1/ws nocanon

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

  # Download as, Fullscreen presentation and Image upload operations
  ProxyPass /lool http://127.0.0.1:9980/lool
  ProxyPassReverse /lool http://127.0.0.1:9980/lool

</VirtualHost>

Notice I’m reverse proxying to http/ws (non-encrypted) destinations.

  1. Docker Image
    Just a couple of points working with docker images.
    Docker images for me are kind of a pain to deal with – and I’m not using Docker Compose (which might be easier)

Some basic commands to help you deal with docker images (Preference these commands with sudo) Another reference (https://www.collaboraoffice.com/code/docker/)

– docker images (Lists all images you’ve downloaded)
– docker ps (Lists all running containers)
– docker run — Takes image, creates container and starts the container (My terminology might be a little off)
– docker stop - Stops running container but keeps all options
– docker start - Really only going to use this command after stopping a container
– docker rm - Destroy container (and any modifications you made to the container are lost since settings are restored to the base image – **See Docker commit)
– docker exec -it /bin/bash - Allows you to actually log into the container and verify settings and change if needed
– docker commit – This will actually create a new base image from current container – This is great if you’ve made changes to the container and then want to save everything.

A couple of steps for me that were very helpful
The collabora Docker container runs a modified version of Ubuntu Xenial with a program known as loolswd that actually does the heavy lifting in terms of documents processing. (I think loolwsd = Libre Office On-Line — I haven’t figured out wsd refers to).

Pull Collabora
sudo docker pull collabora/docker

Start the container (I used a command line like this – I always name my containers to refer to them)
sudo docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 --sysctl net.ipv6.conf.default.disable_ipv6=1 -t -d -p 127.0.0.1:9980:9980 -e 'domain=nextcloud\\.office\\.com' --name="jax" -e "username=admin" -e "password=pass" -e "extra_params=--o:ssl.enable=false --o:ssl.termination=true" --restart always --cap-add MKNOD collabora/code:latest

Explanation – sysctl statements turn off ipv6 routing within container, --name = name of container, username and password will be needed for the ws control. domain refers to the FQDN of the nextcloud host – yes the double slashes are necessary. Lastly ssl.enable states – dont start this container with SSL enabled (Remember SSL encryption in my setup stopped at last reverse proxy) ssl.termination=true basically reiterates this point. (This is option #2 as described on this page: https://www.collaboraoffice.com/code/apache-reverse-proxy/

Some personal steps for me
Once the container is up and running I usually do a few things

-Log into container - sudo docker exec -it <container name> /bin/bash

– Update packages (optional) Once in the container I usually update the packages as with any typical linux distribution – be warned however – if you do this all the language modules will be downloaded and installed which takes a while – if you’re concerned about the size of your container skip this step apt update && apt upgrade

– Install an editor (I prefer vim, but nano/emacs are other options)
apt install vim

– Know location of your configuration file. The loolwsd.xml file (main configuration file for collabora) is located at /etc/loolwsd/loolwsd.xml. All the parameters that are passed on the command line should technically make it into this file. ***Important point for me is that they did not!!! I had to edit this file manually because my changes were not being saved. I’m posting a working copy of this file with specific note for the options of ssl.enable=false and ssl.termination=true (https://pastebin.com/E2uV59B1)

– After I made the manual modifications, I tested modifications by doing a sudo docker restart (or stop,start).

– After I was satisfied with container - I save the current state of the container with the following:
sudo docker commit <container name> collabora/code:updated

– With the save container if could be started on subsequent runs similar to this (Notice I’m calling the new image known as collabora/code:updated versus collabora/code:latest:

sudo docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 --sysctl net.ipv6.conf.default.disable_ipv6=1 -t -d -p 127.0.0.1:9980:9980 --name="jax" --restart always --cap-add MKNOD collabora/code:updated

Hopefully this helps someone as it took me a while to get a working configuration

Lot’s of text …

First of all, from outside can you open your nextcloud instance with https://“nextcloud.yourdomain”?
Second, what the result from outside for https://“office.youdomain”?

Set the debug lebel for yout nexctloud instance and the collabora container.

Regards

Yes I can open https://nextcloud.domain.com from the outside

Yes I can open https://office.domain.com from the outside.

What’s the question exactly?

Hi kevdog,

a little bit late … Do you can open https://office.domain.com/hosting/discovery -the answer shoud be an xml file

Yes I can open the discovery page.

My only problem was the reverse proxies with the ws/wss connections. I was running a double reverse proxy in my setup as explained. I could double reverse proxy any http/https connection, however I couldn’t double reverse proxy the ws/wss connections. mod_wstunnel allows the first ws/wss connection to be proxied to the ws/wss server, however I don’t think this module will work with multiple proxies since I think the headers are changed to http/https. There probably is a way to do what I want with rewrite scripts however I’m too dumb to figure it out.

Thanks for your detailled explaination, i do not understand this in your first post … But i dont know a solution for this double reverse proxy config.

Regards
Ralfi

Impressive, I’ve had enough trouble with one proxy when I decided to switch from nginx to traefik with wildcard certificates and still trying to make collabora work with nxt on the same docker.
Is it for security you chose to use freebsd jail for nxt instead of running it on your ubuntu docker?
I’m going to compare the loolwsd for ssl options which I also played around with to no avail and disable ipv6 in my docker-compose file, thanks for the clear write up :sunny: Regards

@lolo

I’m using FreeNAS and within FreeNAS I installed nextcloud within a FreeBSD Jail. With FreeNAS you don’t really install software directly but rather install software either within jails or virtual machines (a kind of oversimplification). I used this guide to install Nextcloud within the jail: https://www.samueldowling.com/2018/12/08/install-nextcloud-on-freenas-iocage-jail-with-hardened-security/. Since freenas runs with the ZFS file system, I used to directly using this type of installation and with making backups. I suppose you could replicate the system with a Docker image however Freenas/BSD and docker don’t exactly mix well. With any docker image, I usually install linux (ubuntu in my case as a virtual machine and then run docker within the VM). I think at one time you could install RancherOS as a virtual machine and run a docker image, however I haven’t heard this being used in a while – not sure why. Since FreeNAS is a NAS, I thought combining this with Nextcloud would be a good combination. There are probably many different ways to combine these products – I just chose the jail method.