Confusion about SSL keys with Collabora

I’m attempting to get Collabora working correctly with the best security.

I’m using packages on my Debian 8 server with Apache with letsencrypt ssl certificates.

It appears to me that you need ssl certificates and keys defined in /etc/loolwsd/loolwsd.xml. For the loolwsd service to be able to read the appropriate keys, they need to be readable by the lool user.

In my case that would mean compromising some security to allow this to happen or to copy the keys periodically to a directory that the lool user can read, also compromising some security. Additionally, copying the keys is maintenance nightmare since they get updated periodically and will need to be re-copied when that happens.

Is there any reasonable way around this?

1 Like

OK, I may have solved this for myself.

I really think this topic is inadequately covered.

The problem as I’ve alluded to is two-fold. In order for the certs and keys to be secure and to eliminate issues with self-signed keys, there must be a way for them to be securely available to both apache2 and to the loolwsd service.

Digging around the certbot documentation, I found a section on hook scripts. This documentation can be found under https://certbot.eff.org/docs/using.html#renewing-certificates

They provide a deployment hook script for just this occasion, where a service/daemon can’t read the system ssl certs.

You will want to do these as root or with the power of sudo.

Here’s my version, modified for loolwsd:

#!/bin/sh

set -e

for domain in $RENEWED_DOMAINS; do
        case $domain in
        office.nextcloud.com)
                daemon_cert_root=/etc/loolwsd/certs

                # Make sure the certificate and private key files are
                # never world readable, even just for an instant while
                # we're copying them into daemon_cert_root.
                umask 077

                cp "$RENEWED_LINEAGE/fullchain.pem" "$daemon_cert_root/$domain.cert"
                cp "$RENEWED_LINEAGE/privkey.pem" "$daemon_cert_root/$domain.key"

                # Apply the proper file ownership and permissions for
                # the daemon to read its certificate and key.
                chown lool "$daemon_cert_root/$domain.cert" \
                        "$daemon_cert_root/$domain.key"
                chmod 400 "$daemon_cert_root/$domain.cert" \
                        "$daemon_cert_root/$domain.key"

                service loolwsd restart >/dev/null
                ;;
        esac
done

You will need to make an “/etc/loolwsd/certs” directory and chown it to lool and I would highly recommend changing the permissions to rw for the lool user:

mkdir /etc/loolwsd/certs
chmod 700 /etc/loolwsd/certs
chown lool:lool /etc/loolwsd/certs

Then run certbot to get the letsencrypt certs for your Collabora Online domain:

certbot -d office.nextcloud.com

If you’ve run certbot before, you’ll know it wont create the cert’s unless the domain already exists and is being served by your apache server. I have the standard apache reverse proxy entry for my Collabora Online domain that can be found on both the https://www.collaboraoffice.com/code/ site as well as the https://nextcloud.com/collaboraonline/ site. The certbot script should update the SSLCert* lines for you.

Unfortunately, I haven’t been able to confirm the hook file will run on renewal, but I will try to remember to update this post when it renews.

[edit] I forgot to mention that the SSLCert* paths have to be update in /etc/loolwsd/loolwsd.xml to reflect the path and files created above and used by the hook script.

<cert_file_path desc="Path to the cert file" relative="false">/etc/loolwsd/certs/office.nextcloud.com.cert</cert_file_path>
<key_file_path desc="Path to the key file" relative="false">/etc/loolwsd/certs/office.nextcloud.com.key</key_file_path>

It should be obvious, but I’ll mention this for completeness, use your domain for this and not “office.nextcloud.com”.

1 Like

@jimbolaya

Really nice write up however just a few salient points.
Your strategy of changing the directory mask to 700 and ownership to lool:lool really only works if the the loolwsd.xml file and the webserver is being run on the same machine. Unfortunately my setup is a little bit different where I’m running Apache/nextcloud on one machine and the Ubuntu VM/with Docker collabora instance on another. I unfortunately need to share the certs between the two computers and with the virtualized docker container. I shared a common directory within my FreeNAS installation whereby the LetsEncrypt directory containing the certs are shared with Apache/nextcloud application through a shared dataset using FreeBSD jails. Unfortunately with the VM I needed to share the certificate folder through a NFS share. NFS shares are great – however only if UID and GIDs match. Within the docker container the lool user has UID 106 and GID of 107. Unfortunately I couldn’t change the UID/GID of lool within the container unless I recompile the docker container. Because of all the sharing issues I needed to change the directory mask to 744. This mask clearly introduces some security risk issues however its necessary because of the NFS share issue. If the lool user and lool groud had been recreated with the same UID/GID on all machines this wouldn’t be necessary.

I think your strategy works in your case because your running collabora natively and not within the docker container.

Thanks so much for sharing this, helped me a lot.
There’s not much information available on non-docker environments.

Thanks a lot for this good guidance, it helped me a lot.

Although for some reason I still had to create symlinks in
/etc/loolwsd

ln -s certs/office.nextcloud.com.cert cert.pem
ln -s certs/office.nextcloud.com.key key.pem

for the service to start.

Also in loolwsd.xml I set this

<ca_file_path desc=“Path to the ca file” relative=“false”>/var/www/nextcloud/resources/config/ca-bundle.crt</ca_file_path>

I hope it helps someone.

Summary

This text will be hidden

Hi,
I am not sure i got the point. I have a nextcloud server that I can reach by http://nextcloud.xx.net and by https://nextcloud.xx.net (made my certrob)
I installed collabora from ubuntu packages
with http ans ssl not enabled it works.

I wanted to have collabora accessible by https, so I made links as suggested by cessoly, in /etc/loolwsd

but when I change this coade by enable, collabora does not work neither in http or https … i am not sure what I should use in loolwsd.xml
:
ssl desc=“SSL settings”
enable type=“bool” desc=“Controls whether SSL encryption between browser and loolwsd is enabled (do not disable for production deployment). If default is false, must first be compiled with SSL support to enable.” default=“true” false
termination desc=“Connection via proxy where loolwsd acts as working via https, but actually uses http.” type=“bool” default=“true” false

thanks for your help

@cot_al - Do you still need help with this topic?

so far I am running the build in CODE, but yes I am still planing to run the server on ubuntu one day

Good luck to you. I tried actually to run the built-in CODE server and couldn’t get that working!!! Weird.

My server uses letsencrypt and to get it Collabora working I had to copy the certs over to a folder owned by the lool user and group. Putting the paths to the files which were in the /etc/letsencrypt/live/nextcloud.<redacted>.com/ meant the document server failed to start.

So basically now I did

mkdir /etc/loolwsd/certs
cp /etc/letsencrypt/live/nextcloud.<redacted>.com/* /etc/loolwsd/certs
chown -R lool:lool /etc/loolwsd/certs

Then changed the xml configuration file

<cert_file_path desc="Path to the cert file" relative="false">/etc/loolwsd/certs/fullchain.pem</cert_file_path>
<key_file_path desc="Path to the key file" relative="false">/etc/loolwsd/certs/privkey.pem</key_file_path>
<ca_file_path desc="Path to the ca file" relative="false">/etc/loolwsd/certs/chain.pem</ca_file_path> 

So it’s working for now, but will fail when certbot renews the certificates probably, or if the certs change for some reason. Probably I need to create a linux group for these cert files in their original location and put the user lool in this group so it can access them.

Any thoughts on that welcome!

How are you renewing your certs? You probably need a post-hook install command that runs a script to move and cp your certs around and change ownership. Much easier to automate this.

I’m using the certbot automatically created cron job, something I wouldn’t want to tinker with, but perhaps I could just regularly rsync the certs to the required location etc. as you say.

It turns out there is a way to automatically do things with certs when certbot renews them, I found the information here. Basically if you place a script in the directory /etc/letsencrypt/renewal-hooks/deploy/ it will be run every time a letsencrypt renewal is completed successfully. Based on this I developed the following script:

#!/bin/sh
echo "Letsencrypt renewal hook running..."
echo "RENEWED_DOMAINS=$RENEWED_DOMAINS"
echo "RENEWED_LINEAGE=$RENEWED_LINEAGE"

# LibreOffice online (lool) aka collabora online
if grep --quiet "nextcloud.<redacted>.com" <<< "$RENEWED_DOMAINS"; then
  # jabberd requires the private key and cert chain together
  cp --backup=t $RENEWED_LINEAGE/fullchain.pem /etc/loolwsd/cert.pem
  cp --backup=t $RENEWED_LINEAGE/privkey.pem /etc/loolwsd/key.pem
  cp --backup=t $RENEWED_LINEAGE/chain.pem /etc/loolwsd/ca-chain.cert.pem

  chown lool:lool /etc/loolwsd/cert.pem
  chown lool:lool /etc/loolwsd/key.pem
  chown lool:lool /etc/loolwsd/ca-chain.cert.pem

  systemctl restart loolwsd
  echo "loolwsd server.pem updated and loolwsd restarted"
fi

And have put it in there, but I haven’t actually had a renewal yet, so it is untested, except that I manually ran similar commands to get the same effect.

It’s also worth noting I changed the key paths to the defaults in the lool xml configuration file, basically so that when I apt upgrade I can use the new configuration file if it has changed.